| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #vim: set sts=4 sw=4 ts=8 ai: | 
| 2 |  |  |  |  |  |  | # | 
| 3 |  |  |  |  |  |  | # IO::Socket::SSL: | 
| 4 |  |  |  |  |  |  | # provide an interface to SSL connections similar to IO::Socket modules | 
| 5 |  |  |  |  |  |  | # | 
| 6 |  |  |  |  |  |  | # Current Code Shepherd: Steffen Ullrich | 
| 7 |  |  |  |  |  |  | # Code Shepherd before: Peter Behroozi, | 
| 8 |  |  |  |  |  |  | # | 
| 9 |  |  |  |  |  |  | # The original version of this module was written by | 
| 10 |  |  |  |  |  |  | # Marko Asplund, , who drew from | 
| 11 |  |  |  |  |  |  | # Crypt::SSLeay (Net::SSL) by Gisle Aas. | 
| 12 |  |  |  |  |  |  | # | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | package IO::Socket::SSL; | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | our $VERSION = '2.083'; | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 80 |  |  | 80 |  | 1914813 | use IO::Socket; | 
|  | 80 |  |  |  |  | 1378446 |  | 
|  | 80 |  |  |  |  | 316 |  | 
| 19 | 80 |  |  | 80 |  | 57727 | use Net::SSLeay 1.46; | 
|  | 80 |  |  |  |  | 279587 |  | 
|  | 80 |  |  |  |  | 3687 |  | 
| 20 | 80 |  |  | 80 |  | 108182 | use IO::Socket::SSL::PublicSuffix; | 
|  | 80 |  |  |  |  | 227 |  | 
|  | 80 |  |  |  |  | 2623 |  | 
| 21 | 80 |  |  | 80 |  | 548 | use Exporter (); | 
|  | 80 |  |  |  |  | 157 |  | 
|  | 80 |  |  |  |  | 1682 |  | 
| 22 | 80 |  |  | 80 |  | 380 | use Errno qw( EWOULDBLOCK EAGAIN ETIMEDOUT EINTR EPIPE ); | 
|  | 80 |  |  |  |  | 156 |  | 
|  | 80 |  |  |  |  | 8514 |  | 
| 23 | 80 |  |  | 80 |  | 511 | use Carp; | 
|  | 80 |  |  |  |  | 149 |  | 
|  | 80 |  |  |  |  | 3610 |  | 
| 24 | 80 |  |  | 80 |  | 427 | use strict; | 
|  | 80 |  |  |  |  | 150 |  | 
|  | 80 |  |  |  |  | 8071 |  | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | my $use_threads; | 
| 27 |  |  |  |  |  |  | BEGIN { | 
| 28 | 80 | 50 |  | 80 |  | 303 | die "no support for weaken - please install Scalar::Util" if ! do { | 
| 29 | 80 |  |  |  |  | 271 | local $SIG{__DIE__}; | 
| 30 | 80 |  |  |  |  | 355 | eval { require Scalar::Util; Scalar::Util->import("weaken"); 1 } | 
|  | 80 |  |  |  |  | 5808 |  | 
|  | 80 |  |  |  |  | 748 |  | 
| 31 | 80 | 50 |  |  |  | 169 | || eval { require WeakRef; WeakRef->import("weaken"); 1 } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 32 |  |  |  |  |  |  | }; | 
| 33 | 80 |  |  |  |  | 391 | require Config; | 
| 34 | 80 |  |  |  |  | 15885 | $use_threads = $Config::Config{usethreads}; | 
| 35 |  |  |  |  |  |  | } | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | # results from commonly used constant functions from Net::SSLeay for fast access | 
| 39 |  |  |  |  |  |  | my $Net_SSLeay_ERROR_WANT_READ   = Net::SSLeay::ERROR_WANT_READ(); | 
| 40 |  |  |  |  |  |  | my $Net_SSLeay_ERROR_WANT_WRITE  = Net::SSLeay::ERROR_WANT_WRITE(); | 
| 41 |  |  |  |  |  |  | my $Net_SSLeay_ERROR_SYSCALL     = Net::SSLeay::ERROR_SYSCALL(); | 
| 42 |  |  |  |  |  |  | my $Net_SSLeay_ERROR_SSL         = Net::SSLeay::ERROR_SSL(); | 
| 43 |  |  |  |  |  |  | my $Net_SSLeay_VERIFY_NONE       = Net::SSLeay::VERIFY_NONE(); | 
| 44 |  |  |  |  |  |  | my $Net_SSLeay_VERIFY_PEER       = Net::SSLeay::VERIFY_PEER(); | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  |  | 
| 47 | 80 |  |  | 80 |  | 547 | use constant SSL_VERIFY_NONE => &Net::SSLeay::VERIFY_NONE; | 
|  | 80 |  |  |  |  | 154 |  | 
|  | 80 |  |  |  |  | 552 |  | 
| 48 | 80 |  |  | 80 |  | 12322 | use constant SSL_VERIFY_PEER => &Net::SSLeay::VERIFY_PEER; | 
|  | 80 |  |  |  |  | 165 |  | 
|  | 80 |  |  |  |  | 414 |  | 
| 49 | 80 |  |  | 80 |  | 12259 | use constant SSL_VERIFY_FAIL_IF_NO_PEER_CERT => Net::SSLeay::VERIFY_FAIL_IF_NO_PEER_CERT(); | 
|  | 80 |  |  |  |  | 185 |  | 
|  | 80 |  |  |  |  | 585 |  | 
| 50 | 80 |  |  | 80 |  | 10678 | use constant SSL_VERIFY_CLIENT_ONCE => Net::SSLeay::VERIFY_CLIENT_ONCE(); | 
|  | 80 |  |  |  |  | 166 |  | 
|  | 80 |  |  |  |  | 918 |  | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | # from openssl/ssl.h; should be better in Net::SSLeay | 
| 53 | 80 |  |  | 80 |  | 10135 | use constant SSL_SENT_SHUTDOWN => 1; | 
|  | 80 |  |  |  |  | 583 |  | 
|  | 80 |  |  |  |  | 3608 |  | 
| 54 | 80 |  |  | 80 |  | 445 | use constant SSL_RECEIVED_SHUTDOWN => 2; | 
|  | 80 |  |  |  |  | 133 |  | 
|  | 80 |  |  |  |  | 3240 |  | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 80 |  |  | 80 |  | 438 | use constant SSL_OCSP_NO_STAPLE   => 0b00001; | 
|  | 80 |  |  |  |  | 135 |  | 
|  | 80 |  |  |  |  | 3023 |  | 
| 57 | 80 |  |  | 80 |  | 411 | use constant SSL_OCSP_MUST_STAPLE => 0b00010; | 
|  | 80 |  |  |  |  | 132 |  | 
|  | 80 |  |  |  |  | 3067 |  | 
| 58 | 80 |  |  | 80 |  | 406 | use constant SSL_OCSP_FAIL_HARD   => 0b00100; | 
|  | 80 |  |  |  |  | 349 |  | 
|  | 80 |  |  |  |  | 2984 |  | 
| 59 | 80 |  |  | 80 |  | 378 | use constant SSL_OCSP_FULL_CHAIN  => 0b01000; | 
|  | 80 |  |  |  |  | 147 |  | 
|  | 80 |  |  |  |  | 2893 |  | 
| 60 | 80 |  |  | 80 |  | 406 | use constant SSL_OCSP_TRY_STAPLE  => 0b10000; | 
|  | 80 |  |  |  |  | 135 |  | 
|  | 80 |  |  |  |  | 7728 |  | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | # capabilities of underlying Net::SSLeay/openssl | 
| 63 |  |  |  |  |  |  | my $can_client_sni;  # do we support SNI on the client side | 
| 64 |  |  |  |  |  |  | my $can_server_sni;  # do we support SNI on the server side | 
| 65 |  |  |  |  |  |  | my $can_multi_cert;  # RSA and ECC certificate in same context | 
| 66 |  |  |  |  |  |  | my $can_npn;         # do we support NPN (obsolete) | 
| 67 |  |  |  |  |  |  | my $can_alpn;        # do we support ALPN | 
| 68 |  |  |  |  |  |  | my $can_ecdh;        # do we support ECDH key exchange | 
| 69 |  |  |  |  |  |  | my $set_groups_list; # SSL_CTX_set1_groups_list || SSL_CTX_set1_curves_list || undef | 
| 70 |  |  |  |  |  |  | my $can_ocsp;        # do we support OCSP | 
| 71 |  |  |  |  |  |  | my $can_ocsp_staple; # do we support OCSP stapling | 
| 72 |  |  |  |  |  |  | my $can_tckt_keycb;  # TLS ticket key callback | 
| 73 |  |  |  |  |  |  | my $can_pha;         # do we support PHA | 
| 74 |  |  |  |  |  |  | my $session_upref;   # SSL_SESSION_up_ref is implemented | 
| 75 |  |  |  |  |  |  | my %sess_cb;         # SSL_CTX_sess_set_(new|remove)_cb | 
| 76 |  |  |  |  |  |  | my $check_partial_chain; # use X509_V_FLAG_PARTIAL_CHAIN if available | 
| 77 |  |  |  |  |  |  | my $auto_retry;      # (clear|set)_mode SSL_MODE_AUTO_RETRY with OpenSSL 1.1.1+ with non-blocking | 
| 78 |  |  |  |  |  |  | my $ssl_mode_release_buffers = 0; # SSL_MODE_RELEASE_BUFFERS if available | 
| 79 |  |  |  |  |  |  | my $can_ciphersuites; # support for SSL_CTX_set_ciphersuites (TLS 1.3) | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | my $openssl_version; | 
| 82 |  |  |  |  |  |  | my $netssleay_version; | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | BEGIN { | 
| 85 | 80 |  |  | 80 |  | 700 | $openssl_version = Net::SSLeay::OPENSSL_VERSION_NUMBER(); | 
| 86 | 80 |  |  | 80 |  | 444 | $netssleay_version = do { no warnings; $Net::SSLeay::VERSION + 0.0; }; | 
|  | 80 |  |  |  |  | 156 |  | 
|  | 80 |  |  |  |  | 38672 |  | 
|  | 80 |  |  |  |  | 8614 |  | 
|  | 80 |  |  |  |  | 462 |  | 
| 87 | 80 |  |  |  |  | 200 | $can_client_sni = $openssl_version >= 0x10000000; | 
| 88 | 80 |  |  |  |  | 203 | $can_server_sni = defined &Net::SSLeay::get_servername; | 
| 89 | 80 |  | 33 |  |  | 830 | $can_npn = defined &Net::SSLeay::P_next_proto_negotiated && | 
| 90 |  |  |  |  |  |  | ! Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER"); | 
| 91 |  |  |  |  |  |  | # LibreSSL 2.6.1 disabled NPN by keeping the relevant functions | 
| 92 |  |  |  |  |  |  | # available but removed the actual functionality from these functions. | 
| 93 | 80 |  |  |  |  | 381 | $can_alpn = defined &Net::SSLeay::CTX_set_alpn_protos; | 
| 94 | 80 | 50 | 33 |  |  | 848 | $can_ecdh = | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | ($openssl_version >= 0x1010000f) ? 'auto' : | 
| 96 |  |  |  |  |  |  | defined(&Net::SSLeay::CTX_set_ecdh_auto) ? 'can_auto' : | 
| 97 |  |  |  |  |  |  | (defined &Net::SSLeay::CTX_set_tmp_ecdh && | 
| 98 |  |  |  |  |  |  | # There is a regression with elliptic curves on 1.0.1d with 64bit | 
| 99 |  |  |  |  |  |  | # http://rt.openssl.org/Ticket/Display.html?id=2975 | 
| 100 |  |  |  |  |  |  | ( $openssl_version != 0x1000104f | 
| 101 |  |  |  |  |  |  | || length(pack("P",0)) == 4 )) ? 'tmp_ecdh' : | 
| 102 |  |  |  |  |  |  | ''; | 
| 103 | 80 | 50 |  |  |  | 364 | $set_groups_list = | 
|  |  | 50 |  |  |  |  |  | 
| 104 |  |  |  |  |  |  | defined &Net::SSLeay::CTX_set1_groups_list ? \&Net::SSLeay::CTX_set1_groups_list : | 
| 105 |  |  |  |  |  |  | defined &Net::SSLeay::CTX_set1_curves_list ? \&Net::SSLeay::CTX_set1_curves_list : | 
| 106 |  |  |  |  |  |  | undef; | 
| 107 | 80 |  | 33 |  |  | 522 | $can_multi_cert = $can_ecdh | 
| 108 |  |  |  |  |  |  | && $openssl_version >= 0x10002000; | 
| 109 | 80 |  | 33 |  |  | 635 | $can_ocsp = defined &Net::SSLeay::OCSP_cert2ids | 
| 110 |  |  |  |  |  |  | # OCSP got broken in 1.75..1.77 | 
| 111 |  |  |  |  |  |  | && ($netssleay_version < 1.75 || $netssleay_version > 1.77); | 
| 112 | 80 |  | 33 |  |  | 681 | $can_ocsp_staple = $can_ocsp | 
| 113 |  |  |  |  |  |  | && defined &Net::SSLeay::set_tlsext_status_type; | 
| 114 | 80 |  | 33 |  |  | 720 | $can_tckt_keycb  = defined &Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb | 
| 115 |  |  |  |  |  |  | && $netssleay_version >= 1.80; | 
| 116 | 80 |  |  |  |  | 193 | $can_pha = defined &Net::SSLeay::CTX_set_post_handshake_auth; | 
| 117 | 80 |  |  |  |  | 181 | $can_ciphersuites = defined &Net::SSLeay::CTX_set_ciphersuites; | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 80 | 50 |  |  |  | 292 | if (defined &Net::SSLeay::SESSION_up_ref) { | 
| 120 | 0 |  |  |  |  | 0 | $session_upref = 1; | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 80 | 0 | 33 |  |  | 374 | if ($session_upref | 
|  |  |  | 33 |  |  |  |  | 
| 124 |  |  |  |  |  |  | && defined &Net::SSLeay::CTX_sess_set_new_cb | 
| 125 |  |  |  |  |  |  | && defined &Net::SSLeay::CTX_sess_set_remove_cb) { | 
| 126 | 0 |  |  |  |  | 0 | %sess_cb = ( | 
| 127 |  |  |  |  |  |  | new => \&Net::SSLeay::CTX_sess_set_new_cb, | 
| 128 |  |  |  |  |  |  | remove => \&Net::SSLeay::CTX_sess_set_remove_cb, | 
| 129 |  |  |  |  |  |  | ); | 
| 130 |  |  |  |  |  |  | } | 
| 131 |  |  |  |  |  |  |  | 
| 132 | 80 | 50 | 33 |  |  | 453 | if (my $c = defined &Net::SSLeay::CTX_get0_param | 
| 133 |  |  |  |  |  |  | && eval { Net::SSLeay::X509_V_FLAG_PARTIAL_CHAIN() }) { | 
| 134 |  |  |  |  |  |  | $check_partial_chain = sub { | 
| 135 | 0 |  |  |  |  | 0 | my $ctx = shift; | 
| 136 | 0 |  |  |  |  | 0 | my $param = Net::SSLeay::CTX_get0_param($ctx); | 
| 137 | 0 |  |  |  |  | 0 | Net::SSLeay::X509_VERIFY_PARAM_set_flags($param, $c); | 
| 138 | 0 |  |  |  |  | 0 | }; | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  |  | 
| 141 | 80 | 50 |  |  |  | 239 | if (!defined &Net::SSLeay::clear_mode) { | 
| 142 |  |  |  |  |  |  | # assume SSL_CTRL_CLEAR_MODE being 78 since it was always this way | 
| 143 |  |  |  |  |  |  | *Net::SSLeay::clear_mode = sub { | 
| 144 | 0 |  |  | 0 |  | 0 | my ($ctx,$opt) = @_; | 
| 145 | 0 |  |  |  |  | 0 | Net::SSLeay::ctrl($ctx,78,$opt,0); | 
| 146 | 80 |  |  |  |  | 566 | }; | 
| 147 |  |  |  |  |  |  | } | 
| 148 |  |  |  |  |  |  |  | 
| 149 | 80 | 50 |  |  |  | 335 | if ($openssl_version >= 0x10101000) { | 
| 150 |  |  |  |  |  |  | # openssl 1.1.1 enabled SSL_MODE_AUTO_RETRY by default, which is bad for | 
| 151 |  |  |  |  |  |  | # non-blocking sockets | 
| 152 |  |  |  |  |  |  | my $mode_auto_retry = | 
| 153 |  |  |  |  |  |  | # was always 0x00000004 | 
| 154 | 0 |  | 0 |  |  | 0 | eval { Net::SSLeay::MODE_AUTO_RETRY() } || 0x00000004; | 
| 155 |  |  |  |  |  |  | $auto_retry = sub { | 
| 156 | 0 |  |  |  |  | 0 | my ($ssl,$on) = @_; | 
| 157 | 0 | 0 |  |  |  | 0 | if ($on) { | 
| 158 | 0 |  |  |  |  | 0 | Net::SSLeay::set_mode($ssl, $mode_auto_retry); | 
| 159 |  |  |  |  |  |  | } else { | 
| 160 | 0 |  |  |  |  | 0 | Net::SSLeay::clear_mode($ssl, $mode_auto_retry); | 
| 161 |  |  |  |  |  |  | } | 
| 162 |  |  |  |  |  |  | } | 
| 163 | 0 |  |  |  |  | 0 | } | 
| 164 | 80 | 50 |  |  |  | 333 | if ($openssl_version >= 0x10000000) { | 
| 165 |  |  |  |  |  |  | # ssl/ssl.h:#define SSL_MODE_RELEASE_BUFFERS 0x00000010L | 
| 166 | 80 |  |  |  |  | 35182 | $ssl_mode_release_buffers = 0x00000010; | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | my $algo2digest = do { | 
| 171 |  |  |  |  |  |  | my %digest; | 
| 172 |  |  |  |  |  |  | sub { | 
| 173 |  |  |  |  |  |  | my $digest_name = shift; | 
| 174 |  |  |  |  |  |  | return $digest{$digest_name} ||= do { | 
| 175 |  |  |  |  |  |  | Net::SSLeay::SSLeay_add_ssl_algorithms(); | 
| 176 |  |  |  |  |  |  | Net::SSLeay::EVP_get_digestbyname($digest_name) | 
| 177 |  |  |  |  |  |  | or die "Digest algorithm $digest_name is not available"; | 
| 178 |  |  |  |  |  |  | }; | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  | }; | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | my $CTX_tlsv1_3_new; | 
| 183 |  |  |  |  |  |  | if ( defined &Net::SSLeay::CTX_set_min_proto_version | 
| 184 |  |  |  |  |  |  | and defined &Net::SSLeay::CTX_set_max_proto_version | 
| 185 |  |  |  |  |  |  | and my $tls13 = eval { Net::SSLeay::TLS1_3_VERSION() } | 
| 186 |  |  |  |  |  |  | ) { | 
| 187 |  |  |  |  |  |  | $CTX_tlsv1_3_new = sub { | 
| 188 |  |  |  |  |  |  | my $ctx = Net::SSLeay::CTX_new(); | 
| 189 |  |  |  |  |  |  | return $ctx if Net::SSLeay::CTX_set_min_proto_version($ctx,$tls13) | 
| 190 |  |  |  |  |  |  | && Net::SSLeay::CTX_set_max_proto_version($ctx,$tls13); | 
| 191 |  |  |  |  |  |  | Net::SSLeay::CTX_free($ctx); | 
| 192 |  |  |  |  |  |  | return; | 
| 193 |  |  |  |  |  |  | }; | 
| 194 |  |  |  |  |  |  | } | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | # global defaults | 
| 197 |  |  |  |  |  |  | my %DEFAULT_SSL_ARGS = ( | 
| 198 |  |  |  |  |  |  | SSL_check_crl => 0, | 
| 199 |  |  |  |  |  |  | # TLS 1.1 and lower are deprecated with RFC 8996 | 
| 200 |  |  |  |  |  |  | SSL_version => 'SSLv23:!TLSv1:!TLSv1_1:!SSLv3:!SSLv2', | 
| 201 |  |  |  |  |  |  | SSL_verify_callback => undef, | 
| 202 |  |  |  |  |  |  | SSL_verifycn_scheme => undef,  # fallback cn verification | 
| 203 |  |  |  |  |  |  | SSL_verifycn_publicsuffix => undef,  # fallback default list verification | 
| 204 |  |  |  |  |  |  | #SSL_verifycn_name => undef,   # use from PeerAddr/PeerHost - do not override in set_args_filter_hack 'use_defaults' | 
| 205 |  |  |  |  |  |  | SSL_npn_protocols => undef,    # meaning depends whether on server or client side | 
| 206 |  |  |  |  |  |  | SSL_alpn_protocols => undef,   # list of protocols we'll accept/send, for example ['http/1.1','spdy/3.1'] | 
| 207 |  |  |  |  |  |  |  | 
| 208 |  |  |  |  |  |  | # rely on system default but be sure to disable some definitely bad ones | 
| 209 |  |  |  |  |  |  | SSL_cipher_list => 'DEFAULT !EXP !MEDIUM !LOW !eNULL !aNULL !RC4 !DES !MD5 !PSK !SRP', | 
| 210 |  |  |  |  |  |  | ); | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  | my %DEFAULT_SSL_CLIENT_ARGS = ( | 
| 213 |  |  |  |  |  |  | %DEFAULT_SSL_ARGS, | 
| 214 |  |  |  |  |  |  | SSL_verify_mode => SSL_VERIFY_PEER, | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | SSL_ca_file => undef, | 
| 217 |  |  |  |  |  |  | SSL_ca_path => undef, | 
| 218 |  |  |  |  |  |  | ); | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | # set values inside _init to work with perlcc, RT#95452 | 
| 221 |  |  |  |  |  |  | my %DEFAULT_SSL_SERVER_ARGS; | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | # Initialization of OpenSSL internals | 
| 224 |  |  |  |  |  |  | # This will be called once during compilation - perlcc users might need to | 
| 225 |  |  |  |  |  |  | # call it again by hand, see RT#95452 | 
| 226 |  |  |  |  |  |  | { | 
| 227 |  |  |  |  |  |  | sub init { | 
| 228 |  |  |  |  |  |  | # library_init returns false if the library was already initialized. | 
| 229 |  |  |  |  |  |  | # This way we can find out if the library needs to be re-initialized | 
| 230 |  |  |  |  |  |  | # inside code compiled with perlcc | 
| 231 | 159 | 100 |  | 159 | 0 | 12954 | Net::SSLeay::library_init() or return; | 
| 232 |  |  |  |  |  |  |  | 
| 233 | 80 |  |  |  |  | 139337 | Net::SSLeay::load_error_strings(); | 
| 234 | 80 |  |  |  |  | 3362 | Net::SSLeay::OpenSSL_add_all_digests(); | 
| 235 | 80 |  |  |  |  | 718 | Net::SSLeay::randomize(); | 
| 236 |  |  |  |  |  |  |  | 
| 237 |  |  |  |  |  |  | %DEFAULT_SSL_SERVER_ARGS = ( | 
| 238 |  |  |  |  |  |  | %DEFAULT_SSL_ARGS, | 
| 239 |  |  |  |  |  |  | SSL_verify_mode => SSL_VERIFY_NONE, | 
| 240 |  |  |  |  |  |  | SSL_honor_cipher_order => 1,  # trust server to know the best cipher | 
| 241 | 80 | 50 |  |  |  | 70455 | SSL_dh => do { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 242 | 80 |  |  |  |  | 1444 | my $bio = Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem()); | 
| 243 |  |  |  |  |  |  | # generated with: openssl dhparam 2048 | 
| 244 | 80 |  |  |  |  | 576 | Net::SSLeay::BIO_write($bio,<<'DH'); | 
| 245 |  |  |  |  |  |  | -----BEGIN DH PARAMETERS----- | 
| 246 |  |  |  |  |  |  | MIIBCAKCAQEAr8wskArj5+1VCVsnWt/RUR7tXkHJ7mGW7XxrLSPOaFyKyWf8lZht | 
| 247 |  |  |  |  |  |  | iSY2Lc4oa4Zw8wibGQ3faeQu/s8fvPq/aqTxYmyHPKCMoze77QJHtrYtJAosB9SY | 
| 248 |  |  |  |  |  |  | CN7s5Hexxb5/vQ4qlQuOkVrZDiZO9GC4KaH9mJYnCoAsXDhDft6JT0oRVSgtZQnU | 
| 249 |  |  |  |  |  |  | gWFKShIm+JVjN94kGs0TcBEesPTK2g8XVHK9H8AtSUb9BwW2qD/T5RmgNABysApO | 
| 250 |  |  |  |  |  |  | Ps2vlkxjAHjJcqc3O+OiImKik/X2rtBTZjpKmzN3WWTB0RJZCOWaLlDO81D01o1E | 
| 251 |  |  |  |  |  |  | aZecz3Np9KIYey900f+X7zC2bJxEHp95ywIBAg== | 
| 252 |  |  |  |  |  |  | -----END DH PARAMETERS----- | 
| 253 |  |  |  |  |  |  | DH | 
| 254 | 80 |  |  |  |  | 3090 | my $dh = Net::SSLeay::PEM_read_bio_DHparams($bio); | 
| 255 | 80 |  |  |  |  | 496 | Net::SSLeay::BIO_free($bio); | 
| 256 | 80 | 50 |  |  |  | 324 | $dh or die "no DH"; | 
| 257 | 80 |  |  |  |  | 1190 | $dh; | 
| 258 |  |  |  |  |  |  | }, | 
| 259 |  |  |  |  |  |  | ( | 
| 260 |  |  |  |  |  |  | $can_ecdh eq 'auto' ? () : # automatically enabled by openssl | 
| 261 |  |  |  |  |  |  | $can_ecdh eq 'can_auto' ? (SSL_ecdh_curve => 'auto') : | 
| 262 |  |  |  |  |  |  | $can_ecdh eq 'tmp_ecdh' ? ( SSL_ecdh_curve => 'prime256v1' ) : | 
| 263 |  |  |  |  |  |  | (), | 
| 264 |  |  |  |  |  |  | ) | 
| 265 |  |  |  |  |  |  | ); | 
| 266 |  |  |  |  |  |  | } | 
| 267 |  |  |  |  |  |  | # Call it once at compile time and try it at INIT. | 
| 268 |  |  |  |  |  |  | # This should catch all cases of including the module, e.g. 'use' (INIT) or | 
| 269 |  |  |  |  |  |  | # 'require' (compile time) and works also with perlcc | 
| 270 |  |  |  |  |  |  | { | 
| 271 | 80 |  |  | 80 |  | 620 | no warnings; | 
|  | 80 |  |  |  |  | 137 |  | 
|  | 80 |  |  |  |  | 10327 |  | 
| 272 | 79 |  |  | 79 |  | 1565 | INIT { init() } | 
| 273 |  |  |  |  |  |  | init(); | 
| 274 |  |  |  |  |  |  | } | 
| 275 |  |  |  |  |  |  | } | 
| 276 |  |  |  |  |  |  |  | 
| 277 |  |  |  |  |  |  | # global defaults which can be changed using set_defaults | 
| 278 |  |  |  |  |  |  | # either key/value can be set or it can just be set to an external hash | 
| 279 |  |  |  |  |  |  | my $GLOBAL_SSL_ARGS = {}; | 
| 280 |  |  |  |  |  |  | my $GLOBAL_SSL_CLIENT_ARGS = {}; | 
| 281 |  |  |  |  |  |  | my $GLOBAL_SSL_SERVER_ARGS = {}; | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | # hack which is used to filter bad settings from used modules | 
| 284 |  |  |  |  |  |  | my $FILTER_SSL_ARGS = undef; | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | # non-XS Versions of Scalar::Util will fail | 
| 287 |  |  |  |  |  |  | BEGIN{ | 
| 288 | 80 | 50 |  | 80 |  | 312 | die "You need the XS Version of Scalar::Util for dualvar() support" if !do { | 
| 289 | 80 |  |  |  |  | 268 | local $SIG{__DIE__}; local $SIG{__WARN__}; # be silent | 
|  | 80 |  |  |  |  | 347 |  | 
| 290 | 80 |  |  | 80 |  | 634 | eval { use Scalar::Util 'dualvar'; dualvar(0,''); 1 }; | 
|  | 80 |  |  |  |  | 204 |  | 
|  | 80 |  |  |  |  | 5232 |  | 
|  | 80 |  |  |  |  | 137 |  | 
|  | 80 |  |  |  |  | 784 |  | 
|  | 80 |  |  |  |  | 8519 |  | 
| 291 |  |  |  |  |  |  | }; | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | # get constants for SSL_OP_NO_* now, instead calling the related functions | 
| 295 |  |  |  |  |  |  | # every time we setup a connection | 
| 296 |  |  |  |  |  |  | my %SSL_OP_NO; | 
| 297 |  |  |  |  |  |  | for(qw( SSLv2 SSLv3 TLSv1 TLSv1_1 TLSv11:TLSv1_1 TLSv1_2 TLSv12:TLSv1_2 | 
| 298 |  |  |  |  |  |  | TLSv1_3 TLSv13:TLSv1_3 )) { | 
| 299 |  |  |  |  |  |  | my ($k,$op) = m{:} ? split(m{:},$_,2) : ($_,$_); | 
| 300 |  |  |  |  |  |  | my $sub = "Net::SSLeay::OP_NO_$op"; | 
| 301 |  |  |  |  |  |  | local $SIG{__DIE__}; | 
| 302 | 80 |  |  | 80 |  | 545 | $SSL_OP_NO{$k} = eval { no strict 'refs'; &$sub } || 0; | 
|  | 80 |  |  |  |  | 162 |  | 
|  | 80 |  |  |  |  | 11424 |  | 
| 303 |  |  |  |  |  |  | } | 
| 304 |  |  |  |  |  |  |  | 
| 305 |  |  |  |  |  |  | # Make SSL_CTX_clear_options accessible through SSL_CTX_ctrl unless it is | 
| 306 |  |  |  |  |  |  | # already implemented in Net::SSLeay | 
| 307 |  |  |  |  |  |  | if (!defined &Net::SSLeay::CTX_clear_options) { | 
| 308 |  |  |  |  |  |  | *Net::SSLeay::CTX_clear_options = sub { | 
| 309 | 21 |  |  | 21 |  | 93 | my ($ctx,$opt) = @_; | 
| 310 |  |  |  |  |  |  | # 77 = SSL_CTRL_CLEAR_OPTIONS | 
| 311 | 21 |  |  |  |  | 141 | Net::SSLeay::CTX_ctrl($ctx,77,$opt,0); | 
| 312 |  |  |  |  |  |  | }; | 
| 313 |  |  |  |  |  |  | } | 
| 314 |  |  |  |  |  |  |  | 
| 315 |  |  |  |  |  |  | # Try to work around problems with alternative trust path by default, RT#104759 | 
| 316 |  |  |  |  |  |  | my $DEFAULT_X509_STORE_flags = 0; | 
| 317 |  |  |  |  |  |  | { | 
| 318 |  |  |  |  |  |  | local $SIG{__DIE__}; | 
| 319 |  |  |  |  |  |  | eval { $DEFAULT_X509_STORE_flags |= Net::SSLeay::X509_V_FLAG_TRUSTED_FIRST() }; | 
| 320 |  |  |  |  |  |  | } | 
| 321 |  |  |  |  |  |  |  | 
| 322 |  |  |  |  |  |  | our $DEBUG; | 
| 323 | 80 |  |  | 80 |  | 559 | use vars qw(@ISA $SSL_ERROR @EXPORT); | 
|  | 80 |  |  |  |  | 160 |  | 
|  | 80 |  |  |  |  | 7771 |  | 
| 324 |  |  |  |  |  |  |  | 
| 325 |  |  |  |  |  |  | { | 
| 326 |  |  |  |  |  |  | # These constants will be used in $! at return from SSL_connect, | 
| 327 |  |  |  |  |  |  | # SSL_accept, _generic_(read|write), thus notifying the caller | 
| 328 |  |  |  |  |  |  | # the usual way of problems. Like with EWOULDBLOCK, EINPROGRESS.. | 
| 329 |  |  |  |  |  |  | # these are especially important for non-blocking sockets | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | my $x = $Net_SSLeay_ERROR_WANT_READ; | 
| 332 | 80 |  |  | 80 |  | 528 | use constant SSL_WANT_READ  => dualvar( \$x, 'SSL wants a read first' ); | 
|  | 80 |  |  |  |  | 159 |  | 
|  | 80 |  |  |  |  | 6816 |  | 
| 333 |  |  |  |  |  |  | my $y = $Net_SSLeay_ERROR_WANT_WRITE; | 
| 334 | 80 |  |  | 80 |  | 539 | use constant SSL_WANT_WRITE => dualvar( \$y, 'SSL wants a write first' ); | 
|  | 80 |  |  |  |  | 166 |  | 
|  | 80 |  |  |  |  | 40953 |  | 
| 335 |  |  |  |  |  |  |  | 
| 336 |  |  |  |  |  |  | @EXPORT = qw( | 
| 337 |  |  |  |  |  |  | SSL_WANT_READ SSL_WANT_WRITE SSL_VERIFY_NONE SSL_VERIFY_PEER | 
| 338 |  |  |  |  |  |  | SSL_VERIFY_FAIL_IF_NO_PEER_CERT SSL_VERIFY_CLIENT_ONCE | 
| 339 |  |  |  |  |  |  | SSL_OCSP_NO_STAPLE SSL_OCSP_TRY_STAPLE SSL_OCSP_MUST_STAPLE | 
| 340 |  |  |  |  |  |  | SSL_OCSP_FAIL_HARD SSL_OCSP_FULL_CHAIN | 
| 341 |  |  |  |  |  |  | $SSL_ERROR GEN_DNS GEN_IPADD | 
| 342 |  |  |  |  |  |  | ); | 
| 343 |  |  |  |  |  |  | } | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | my @caller_force_inet4; # in case inet4 gets forced we store here who forced it | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | my $IOCLASS; | 
| 348 |  |  |  |  |  |  | my $family_key; # 'Domain'||'Family' | 
| 349 |  |  |  |  |  |  | BEGIN { | 
| 350 |  |  |  |  |  |  | # declare @ISA depending of the installed socket class | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | # try to load inet_pton from Socket or Socket6 and make sure it is usable | 
| 353 | 80 |  |  | 80 |  | 511 | local $SIG{__DIE__}; local $SIG{__WARN__}; # be silent | 
|  | 80 |  |  |  |  | 282 |  | 
| 354 |  |  |  |  |  |  | my $ip6 = eval { | 
| 355 |  |  |  |  |  |  | require Socket; | 
| 356 |  |  |  |  |  |  | Socket->VERSION(1.95); | 
| 357 |  |  |  |  |  |  | Socket::inet_pton( AF_INET6(),'::1') && AF_INET6() or die; | 
| 358 |  |  |  |  |  |  | Socket->import( qw/inet_pton NI_NUMERICHOST NI_NUMERICSERV/ ); | 
| 359 |  |  |  |  |  |  | # behavior different to Socket6::getnameinfo - wrap | 
| 360 |  |  |  |  |  |  | *_getnameinfo = sub { | 
| 361 | 0 |  |  | 0 |  | 0 | my ($err,$host,$port) = Socket::getnameinfo(@_) or return; | 
| 362 | 0 |  |  |  |  | 0 | return if $err; | 
| 363 | 0 |  |  |  |  | 0 | return ($host,$port); | 
| 364 |  |  |  |  |  |  | }; | 
| 365 |  |  |  |  |  |  | 'Socket'; | 
| 366 | 80 |  | 50 |  |  | 169 | } || eval { | 
| 367 |  |  |  |  |  |  | require Socket6; | 
| 368 |  |  |  |  |  |  | Socket6::inet_pton( AF_INET6(),'::1') && AF_INET6() or die; | 
| 369 |  |  |  |  |  |  | Socket6->import( qw/inet_pton NI_NUMERICHOST NI_NUMERICSERV/ ); | 
| 370 |  |  |  |  |  |  | # behavior different to Socket::getnameinfo - wrap | 
| 371 |  |  |  |  |  |  | *_getnameinfo = sub { return Socket6::getnameinfo(@_); }; | 
| 372 |  |  |  |  |  |  | 'Socket6'; | 
| 373 |  |  |  |  |  |  | } || undef; | 
| 374 |  |  |  |  |  |  |  | 
| 375 |  |  |  |  |  |  | # try IO::Socket::IP or IO::Socket::INET6 for IPv6 support | 
| 376 | 80 |  |  |  |  | 179 | $family_key = 'Domain'; # traditional | 
| 377 | 80 | 50 |  |  |  | 360 | if ($ip6) { | 
| 378 |  |  |  |  |  |  | # if we have IO::Socket::IP >= 0.31 we will use this in preference | 
| 379 |  |  |  |  |  |  | # because it can handle both IPv4 and IPv6 | 
| 380 | 80 | 100 |  |  |  | 184 | if ( eval { | 
|  |  | 50 |  |  |  |  |  | 
| 381 | 80 |  |  |  |  | 49016 | require IO::Socket::IP; | 
| 382 | 80 |  |  |  |  | 1173988 | IO::Socket::IP->VERSION(0.31) | 
| 383 |  |  |  |  |  |  | }) { | 
| 384 | 79 |  |  |  |  | 1596 | @ISA = qw(IO::Socket::IP); | 
| 385 | 79 |  |  |  |  | 3082 | constant->import( CAN_IPV6 => "IO::Socket::IP" ); | 
| 386 | 79 |  |  |  |  | 217 | $family_key = 'Family'; | 
| 387 | 79 |  |  |  |  | 193 | $IOCLASS = "IO::Socket::IP"; | 
| 388 |  |  |  |  |  |  |  | 
| 389 |  |  |  |  |  |  | # if we have IO::Socket::INET6 we will use this not IO::Socket::INET | 
| 390 |  |  |  |  |  |  | # because it can handle both IPv4 and IPv6 | 
| 391 |  |  |  |  |  |  | # require at least 2.62 because of several problems before that version | 
| 392 | 1 |  |  |  |  | 214 | } elsif( eval { require IO::Socket::INET6; IO::Socket::INET6->VERSION(2.62) } ) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 393 | 0 |  |  |  |  | 0 | @ISA = qw(IO::Socket::INET6); | 
| 394 | 0 |  |  |  |  | 0 | constant->import( CAN_IPV6 => "IO::Socket::INET6" ); | 
| 395 | 0 |  |  |  |  | 0 | $IOCLASS = "IO::Socket::INET6"; | 
| 396 |  |  |  |  |  |  | } else { | 
| 397 | 1 |  |  |  |  | 3 | $ip6 = '' | 
| 398 |  |  |  |  |  |  | } | 
| 399 |  |  |  |  |  |  | } | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | # fall back to IO::Socket::INET for IPv4 only | 
| 402 | 80 | 100 |  |  |  | 598 | if (!$ip6) { | 
| 403 | 1 |  |  |  |  | 20 | @ISA = qw(IO::Socket::INET); | 
| 404 | 1 |  |  |  |  | 2 | $IOCLASS = "IO::Socket::INET"; | 
| 405 | 1 |  |  |  |  | 64 | constant->import(CAN_IPV6 => ''); | 
| 406 | 1 | 50 |  |  |  | 33 | if (!defined $ip6) { | 
| 407 | 0 |  |  |  |  | 0 | constant->import(NI_NUMERICHOST => 1); | 
| 408 | 0 |  |  |  |  | 0 | constant->import(NI_NUMERICSERV => 2); | 
| 409 |  |  |  |  |  |  | } | 
| 410 |  |  |  |  |  |  | } | 
| 411 |  |  |  |  |  |  |  | 
| 412 |  |  |  |  |  |  | #Make $DEBUG another name for $Net::SSLeay::trace | 
| 413 | 80 |  |  |  |  | 254 | *DEBUG = \$Net::SSLeay::trace; | 
| 414 |  |  |  |  |  |  |  | 
| 415 |  |  |  |  |  |  | #Compatibility | 
| 416 | 80 |  |  |  |  | 17367 | *ERROR = \$SSL_ERROR; | 
| 417 |  |  |  |  |  |  | } | 
| 418 |  |  |  |  |  |  |  | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | sub DEBUG { | 
| 421 | 0 | 0 |  | 0 | 0 | 0 | $DEBUG or return; | 
| 422 | 0 |  |  |  |  | 0 | my (undef,$file,$line,$sub) = caller(1); | 
| 423 | 0 | 0 |  |  |  | 0 | if ($sub =~m{^IO::Socket::SSL::(?:error|(_internal_error))$}) { | 
| 424 | 0 | 0 |  |  |  | 0 | (undef,$file,$line) = caller(2) if $1; | 
| 425 |  |  |  |  |  |  | } else { | 
| 426 | 0 |  |  |  |  | 0 | (undef,$file,$line) = caller; | 
| 427 |  |  |  |  |  |  | } | 
| 428 | 0 |  |  |  |  | 0 | my $msg = shift; | 
| 429 | 0 | 0 |  |  |  | 0 | $file = '...'.substr( $file,-17 ) if length($file)>20; | 
| 430 | 0 | 0 |  |  |  | 0 | $msg = sprintf $msg,@_ if @_; | 
| 431 | 0 |  |  |  |  | 0 | print STDERR "DEBUG: $file:$line: $msg\n"; | 
| 432 |  |  |  |  |  |  | } | 
| 433 |  |  |  |  |  |  |  | 
| 434 |  |  |  |  |  |  | BEGIN { | 
| 435 |  |  |  |  |  |  | # import some constants from Net::SSLeay or use hard-coded defaults | 
| 436 |  |  |  |  |  |  | # if Net::SSLeay isn't recent enough to provide the constants | 
| 437 | 80 |  |  | 80 |  | 643 | my %const = ( | 
| 438 |  |  |  |  |  |  | NID_CommonName => 13, | 
| 439 |  |  |  |  |  |  | GEN_DNS => 2, | 
| 440 |  |  |  |  |  |  | GEN_IPADD => 7, | 
| 441 |  |  |  |  |  |  | ); | 
| 442 | 80 |  |  |  |  | 700 | while ( my ($name,$value) = each %const ) { | 
| 443 | 80 |  |  | 80 |  | 640 | no strict 'refs'; | 
|  | 80 |  |  |  |  | 174 |  | 
|  | 80 |  |  |  |  | 8581 |  | 
| 444 | 240 |  | 50 | 614 |  | 2586 | *{$name} = UNIVERSAL::can( 'Net::SSLeay', $name ) || sub { $value }; | 
|  | 240 |  |  |  |  | 2080 |  | 
|  | 614 |  |  |  |  | 2556 |  | 
| 445 |  |  |  |  |  |  | } | 
| 446 |  |  |  |  |  |  |  | 
| 447 | 80 |  |  |  |  | 264 | *idn_to_ascii = \&IO::Socket::SSL::PublicSuffix::idn_to_ascii; | 
| 448 | 80 |  |  |  |  | 871036 | *idn_to_unicode = \&IO::Socket::SSL::PublicSuffix::idn_to_unicode; | 
| 449 |  |  |  |  |  |  | } | 
| 450 |  |  |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | my $OPENSSL_LIST_SEPARATOR = $^O =~m{^(?:(dos|os2|mswin32|netware)|vms)$}i | 
| 452 |  |  |  |  |  |  | ? $1 ? ';' : ',' : ':'; | 
| 453 |  |  |  |  |  |  | my $CHECK_SSL_PATH = sub { | 
| 454 |  |  |  |  |  |  | my %args = (@_ == 1) ? ('',@_) : @_; | 
| 455 |  |  |  |  |  |  | for my $type (keys %args) { | 
| 456 |  |  |  |  |  |  | my $path = $args{$type}; | 
| 457 |  |  |  |  |  |  | if (!$type) { | 
| 458 |  |  |  |  |  |  | delete $args{$type}; | 
| 459 |  |  |  |  |  |  | $type = (ref($path) || -d $path) ? 'SSL_ca_path' : 'SSL_ca_file'; | 
| 460 |  |  |  |  |  |  | $args{$type} = $path; | 
| 461 |  |  |  |  |  |  | } | 
| 462 |  |  |  |  |  |  |  | 
| 463 |  |  |  |  |  |  | next if ref($path) eq 'SCALAR' && ! $$path; | 
| 464 |  |  |  |  |  |  | if ($type eq 'SSL_ca_file') { | 
| 465 |  |  |  |  |  |  | die "SSL_ca_file $path can't be used: $!" | 
| 466 |  |  |  |  |  |  | if ! open(my $fh,'<',$path); | 
| 467 |  |  |  |  |  |  | } elsif ($type eq 'SSL_ca_path') { | 
| 468 |  |  |  |  |  |  | $path = [ split($OPENSSL_LIST_SEPARATOR,$path) ] if !ref($path); | 
| 469 |  |  |  |  |  |  | my @err; | 
| 470 |  |  |  |  |  |  | for my $d (ref($path) ? @$path : $path) { | 
| 471 |  |  |  |  |  |  | if (! -d $d) { | 
| 472 |  |  |  |  |  |  | push @err, "SSL_ca_path $d does not exist"; | 
| 473 |  |  |  |  |  |  | } elsif (! opendir(my $dh,$d)) { | 
| 474 |  |  |  |  |  |  | push @err, "SSL_ca_path $d is not accessible: $!" | 
| 475 |  |  |  |  |  |  | } else { | 
| 476 |  |  |  |  |  |  | @err = (); | 
| 477 |  |  |  |  |  |  | last | 
| 478 |  |  |  |  |  |  | } | 
| 479 |  |  |  |  |  |  | } | 
| 480 |  |  |  |  |  |  | die "@err" if @err; | 
| 481 |  |  |  |  |  |  | } | 
| 482 |  |  |  |  |  |  | } | 
| 483 |  |  |  |  |  |  | return %args; | 
| 484 |  |  |  |  |  |  | }; | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  |  | 
| 487 |  |  |  |  |  |  | { | 
| 488 |  |  |  |  |  |  | my %default_ca; | 
| 489 |  |  |  |  |  |  | my $ca_detected; # 0: never detect, undef: need to (re)detect | 
| 490 |  |  |  |  |  |  | my $openssldir; | 
| 491 |  |  |  |  |  |  |  | 
| 492 |  |  |  |  |  |  | sub default_ca { | 
| 493 | 167 | 100 |  | 167 | 1 | 6502 | if (@_) { | 
| 494 |  |  |  |  |  |  | # user defined default CA or reset | 
| 495 | 3 | 50 |  |  |  | 108 | if ( @_ > 1 ) { | 
|  |  | 50 |  |  |  |  |  | 
| 496 | 0 |  |  |  |  | 0 | %default_ca = @_; | 
| 497 | 0 |  |  |  |  | 0 | $ca_detected  = 0; | 
| 498 |  |  |  |  |  |  | } elsif ( my $path = shift ) { | 
| 499 | 3 |  |  |  |  | 50 | %default_ca = $CHECK_SSL_PATH->($path); | 
| 500 | 3 |  |  |  |  | 10 | $ca_detected  = 0; | 
| 501 |  |  |  |  |  |  | } else { | 
| 502 | 0 |  |  |  |  | 0 | $ca_detected = undef; | 
| 503 |  |  |  |  |  |  | } | 
| 504 |  |  |  |  |  |  | } | 
| 505 | 167 | 100 |  |  |  | 2692 | return %default_ca if defined $ca_detected; | 
| 506 |  |  |  |  |  |  |  | 
| 507 |  |  |  |  |  |  | # SSLEAY_DIR was 5 up to OpenSSL 1.1, then switched to 4 and got | 
| 508 |  |  |  |  |  |  | # renamed to OPENSSL_DIR. Unfortunately it is not exported as constant | 
| 509 |  |  |  |  |  |  | # by Net::SSLeay so we use the fixed number. | 
| 510 | 45 | 0 | 33 |  |  | 2314 | $openssldir ||= | 
|  |  | 50 |  |  |  |  |  | 
| 511 |  |  |  |  |  |  | Net::SSLeay::SSLeay_version(5) =~m{^OPENSSLDIR: "(.+)"$} ? $1 : | 
| 512 |  |  |  |  |  |  | Net::SSLeay::SSLeay_version(4) =~m{^OPENSSLDIR: "(.+)"$} ? $1 : | 
| 513 |  |  |  |  |  |  | 'cannot-determine-openssldir-from-ssleay-version'; | 
| 514 |  |  |  |  |  |  |  | 
| 515 |  |  |  |  |  |  | # (re)detect according to openssl crypto/cryptlib.h | 
| 516 |  |  |  |  |  |  | my $dir = $ENV{SSL_CERT_DIR} | 
| 517 | 45 |  | 33 |  |  | 1348 | || ( $^O =~m{vms}i ? "SSLCERTS:":"$openssldir/certs" ); | 
| 518 | 45 | 50 |  |  |  | 4628 | if ( opendir(my $dh,$dir)) { | 
| 519 | 45 |  |  |  |  | 23664 | FILES: for my $f (  grep { m{^[a-f\d]{8}(\.\d+)?$} } readdir($dh) ) { | 
|  | 20115 |  |  |  |  | 52063 |  | 
| 520 | 45 | 50 |  |  |  | 3816 | open( my $fh,'<',"$dir/$f") or next; | 
| 521 | 45 |  |  |  |  | 1943 | while (my $line = <$fh>) { | 
| 522 | 45 | 50 |  |  |  | 602 | $line =~m{^-+BEGIN (X509 |TRUSTED |)CERTIFICATE-} or next; | 
| 523 | 45 |  |  |  |  | 319 | $default_ca{SSL_ca_path} = $dir; | 
| 524 | 45 |  |  |  |  | 1207 | last FILES; | 
| 525 |  |  |  |  |  |  | } | 
| 526 |  |  |  |  |  |  | } | 
| 527 |  |  |  |  |  |  | } | 
| 528 |  |  |  |  |  |  | my $file = $ENV{SSL_CERT_FILE} | 
| 529 | 45 |  | 33 |  |  | 2363 | || ( $^O =~m{vms}i ? "SSLCERTS:cert.pem":"$openssldir/cert.pem" ); | 
| 530 | 45 | 50 |  |  |  | 1170 | if ( open(my $fh,'<',$file)) { | 
| 531 | 0 |  |  |  |  | 0 | while (my $line = <$fh>) { | 
| 532 | 0 | 0 |  |  |  | 0 | $line =~m{^-+BEGIN (X509 |TRUSTED |)CERTIFICATE-} or next; | 
| 533 | 0 |  |  |  |  | 0 | $default_ca{SSL_ca_file} = $file; | 
| 534 | 0 |  |  |  |  | 0 | last; | 
| 535 |  |  |  |  |  |  | } | 
| 536 |  |  |  |  |  |  | } | 
| 537 |  |  |  |  |  |  |  | 
| 538 | 45 | 0 | 33 |  |  | 679 | $default_ca{SSL_ca_file} = Mozilla::CA::SSL_ca_file() if ! %default_ca && do { | 
| 539 | 0 |  |  |  |  | 0 | local $SIG{__DIE__}; | 
| 540 | 0 |  |  |  |  | 0 | eval { require Mozilla::CA; 1 }; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 541 |  |  |  |  |  |  | }; | 
| 542 |  |  |  |  |  |  |  | 
| 543 | 45 |  |  |  |  | 143 | $ca_detected = 1; | 
| 544 | 45 |  |  |  |  | 1715 | return %default_ca; | 
| 545 |  |  |  |  |  |  | } | 
| 546 |  |  |  |  |  |  | } | 
| 547 |  |  |  |  |  |  |  | 
| 548 |  |  |  |  |  |  |  | 
| 549 |  |  |  |  |  |  | # Export some stuff | 
| 550 |  |  |  |  |  |  | # inet4|inet6|debug will be handled by myself, everything | 
| 551 |  |  |  |  |  |  | # else will be handled the Exporter way | 
| 552 |  |  |  |  |  |  | sub import { | 
| 553 | 159 |  |  | 159 |  | 206858 | my $class = shift; | 
| 554 |  |  |  |  |  |  |  | 
| 555 | 159 |  |  |  |  | 448 | my @export; | 
| 556 | 159 |  |  |  |  | 660 | foreach (@_) { | 
| 557 | 1 | 50 |  |  |  | 15 | if ( /^inet4$/i ) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 558 |  |  |  |  |  |  | # explicitly fall back to inet4 | 
| 559 | 0 |  |  |  |  | 0 | @ISA = 'IO::Socket::INET'; | 
| 560 | 0 |  |  |  |  | 0 | @caller_force_inet4 = caller(); # save for warnings for 'inet6' case | 
| 561 |  |  |  |  |  |  | } elsif ( /^inet6$/i ) { | 
| 562 |  |  |  |  |  |  | # check if we have already ipv6 as base | 
| 563 | 0 | 0 | 0 |  |  | 0 | if ( ! UNIVERSAL::isa( $class, 'IO::Socket::INET6') | 
| 564 |  |  |  |  |  |  | and ! UNIVERSAL::isa( $class, 'IO::Socket::IP' )) { | 
| 565 |  |  |  |  |  |  | # either we don't support it or we disabled it by explicitly | 
| 566 |  |  |  |  |  |  | # loading it with 'inet4'. In this case re-enable but warn | 
| 567 |  |  |  |  |  |  | # because this is probably an error | 
| 568 | 0 |  |  |  |  | 0 | if ( CAN_IPV6 ) { | 
| 569 | 0 |  |  |  |  | 0 | @ISA = ( CAN_IPV6 ); | 
| 570 | 0 |  |  |  |  | 0 | warn "IPv6 support re-enabled in __PACKAGE__, got disabled in file $caller_force_inet4[1] line $caller_force_inet4[2]"; | 
| 571 |  |  |  |  |  |  | } else { | 
| 572 |  |  |  |  |  |  | die "INET6 is not supported, install IO::Socket::IP"; | 
| 573 |  |  |  |  |  |  | } | 
| 574 |  |  |  |  |  |  | } | 
| 575 |  |  |  |  |  |  | } elsif ( /^:?debug(\d+)/ ) { | 
| 576 | 1 |  |  |  |  | 4 | $DEBUG=$1; | 
| 577 |  |  |  |  |  |  | } else { | 
| 578 | 2 |  |  |  |  | 8 | push @export,$_ | 
| 579 |  |  |  |  |  |  | } | 
| 580 |  |  |  |  |  |  | } | 
| 581 |  |  |  |  |  |  |  | 
| 582 | 159 |  |  |  |  | 3112 | @_ = ( $class,@export ); | 
| 583 | 157 |  |  |  |  | 132830 | goto &Exporter::import; | 
| 584 |  |  |  |  |  |  | } | 
| 585 |  |  |  |  |  |  |  | 
| 586 |  |  |  |  |  |  | my %SSL_OBJECT; | 
| 587 |  |  |  |  |  |  | my %CREATED_IN_THIS_THREAD; | 
| 588 | 0 |  |  | 0 |  | 0 | sub CLONE { %CREATED_IN_THIS_THREAD = (); } | 
| 589 |  |  |  |  |  |  |  | 
| 590 |  |  |  |  |  |  | # all keys used internally, these should be cleaned up at end | 
| 591 |  |  |  |  |  |  | my @all_my_keys = qw( | 
| 592 |  |  |  |  |  |  | _SSL_arguments | 
| 593 |  |  |  |  |  |  | _SSL_certificate | 
| 594 |  |  |  |  |  |  | _SSL_ctx | 
| 595 |  |  |  |  |  |  | _SSL_fileno | 
| 596 |  |  |  |  |  |  | _SSL_in_DESTROY | 
| 597 |  |  |  |  |  |  | _SSL_ioclass_downgrade | 
| 598 |  |  |  |  |  |  | _SSL_ioclass_upgraded | 
| 599 |  |  |  |  |  |  | _SSL_last_err | 
| 600 |  |  |  |  |  |  | _SSL_object | 
| 601 |  |  |  |  |  |  | _SSL_ocsp_verify | 
| 602 |  |  |  |  |  |  | _SSL_opened | 
| 603 |  |  |  |  |  |  | _SSL_opening | 
| 604 |  |  |  |  |  |  | _SSL_servername | 
| 605 |  |  |  |  |  |  | _SSL_msg_callback | 
| 606 |  |  |  |  |  |  | ); | 
| 607 |  |  |  |  |  |  |  | 
| 608 |  |  |  |  |  |  |  | 
| 609 |  |  |  |  |  |  | # we have callbacks associated with contexts, but have no way to access the | 
| 610 |  |  |  |  |  |  | # current SSL object from these callbacks. To work around this | 
| 611 |  |  |  |  |  |  | # CURRENT_SSL_OBJECT will be set before calling Net::SSLeay::{connect,accept} | 
| 612 |  |  |  |  |  |  | # and reset afterwards, so we have access to it inside _internal_error. | 
| 613 |  |  |  |  |  |  | my $CURRENT_SSL_OBJECT; | 
| 614 |  |  |  |  |  |  |  | 
| 615 |  |  |  |  |  |  | # You might be expecting to find a new() subroutine here, but that is | 
| 616 |  |  |  |  |  |  | # not how IO::Socket::INET works.  All configuration gets performed in | 
| 617 |  |  |  |  |  |  | # the calls to configure() and either connect() or accept(). | 
| 618 |  |  |  |  |  |  |  | 
| 619 |  |  |  |  |  |  | #Call to configure occurs when a new socket is made using | 
| 620 |  |  |  |  |  |  | #IO::Socket::INET.  Returns false (empty list) on failure. | 
| 621 |  |  |  |  |  |  | sub configure { | 
| 622 | 116 |  |  | 116 | 0 | 4189191 | my ($self, $arg_hash) = @_; | 
| 623 | 116 | 50 |  |  |  | 1038 | return _invalid_object() unless($self); | 
| 624 |  |  |  |  |  |  |  | 
| 625 |  |  |  |  |  |  | # force initial blocking | 
| 626 |  |  |  |  |  |  | # otherwise IO::Socket::SSL->new might return undef if the | 
| 627 |  |  |  |  |  |  | # socket is nonblocking and it fails to connect immediately | 
| 628 |  |  |  |  |  |  | # for real nonblocking behavior one should create a nonblocking | 
| 629 |  |  |  |  |  |  | # socket and later call connect explicitly | 
| 630 | 116 |  |  |  |  | 633 | my $blocking = delete $arg_hash->{Blocking}; | 
| 631 |  |  |  |  |  |  |  | 
| 632 |  |  |  |  |  |  | # because Net::HTTPS simple redefines blocking() to {} (e.g. | 
| 633 |  |  |  |  |  |  | # return undef) and IO::Socket::INET does not like this we | 
| 634 |  |  |  |  |  |  | # set Blocking only explicitly if it was set | 
| 635 | 116 | 100 |  |  |  | 713 | $arg_hash->{Blocking} = 1 if defined ($blocking); | 
| 636 |  |  |  |  |  |  |  | 
| 637 | 116 | 100 |  |  |  | 974 | $self->configure_SSL($arg_hash) || return; | 
| 638 |  |  |  |  |  |  |  | 
| 639 | 112 | 100 | 66 |  |  | 1606 | if ($arg_hash->{$family_key} ||= $arg_hash->{Domain} || $arg_hash->{Family}) { | 
|  |  |  | 66 |  |  |  |  | 
| 640 |  |  |  |  |  |  | # Hack to work around the problem that IO::Socket::IP defaults to | 
| 641 |  |  |  |  |  |  | # AI_ADDRCONFIG which creates problems if we have only the loopback | 
| 642 |  |  |  |  |  |  | # interface. If we already know the family this flag is more harmful | 
| 643 |  |  |  |  |  |  | # then useful. | 
| 644 |  |  |  |  |  |  | $arg_hash->{GetAddrInfoFlags} = 0 if $IOCLASS eq 'IO::Socket::IP' | 
| 645 | 68 | 50 | 33 |  |  | 723 | && ! defined $arg_hash->{GetAddrInfoFlags}; | 
| 646 |  |  |  |  |  |  | } | 
| 647 | 112 | 100 |  |  |  | 1146 | return $self->_internal_error("@ISA configuration failed",0) | 
| 648 |  |  |  |  |  |  | if ! $self->SUPER::configure($arg_hash); | 
| 649 |  |  |  |  |  |  |  | 
| 650 | 106 | 100 | 66 |  |  | 9307 | $self->blocking(0) if defined $blocking && !$blocking; | 
| 651 | 106 |  |  |  |  | 862 | return $self; | 
| 652 |  |  |  |  |  |  | } | 
| 653 |  |  |  |  |  |  |  | 
| 654 |  |  |  |  |  |  | sub configure_SSL { | 
| 655 | 277 |  |  | 277 | 0 | 1194 | my ($self, $arg_hash) = @_; | 
| 656 |  |  |  |  |  |  |  | 
| 657 | 277 |  | 50 |  |  | 5157 | $arg_hash->{Proto} ||= 'tcp'; | 
| 658 | 277 |  |  |  |  | 767 | my $is_server = $arg_hash->{SSL_server}; | 
| 659 | 277 | 100 |  |  |  | 1315 | if ( ! defined $is_server ) { | 
| 660 | 196 |  | 100 |  |  | 3212 | $is_server = $arg_hash->{SSL_server} = $arg_hash->{Listen} || 0; | 
| 661 |  |  |  |  |  |  | } | 
| 662 |  |  |  |  |  |  |  | 
| 663 |  |  |  |  |  |  | # add user defined defaults, maybe after filtering | 
| 664 | 277 | 50 |  |  |  | 1178 | $FILTER_SSL_ARGS->($is_server,$arg_hash) if $FILTER_SSL_ARGS; | 
| 665 |  |  |  |  |  |  |  | 
| 666 | 277 |  |  |  |  | 857 | delete @{*$self}{@all_my_keys}; | 
|  | 277 |  |  |  |  | 3152 |  | 
| 667 | 277 |  |  |  |  | 893 | ${*$self}{_SSL_opened} = $is_server; | 
|  | 277 |  |  |  |  | 885 |  | 
| 668 | 277 |  |  |  |  | 623 | ${*$self}{_SSL_arguments} = $arg_hash; | 
|  | 277 |  |  |  |  | 1079 |  | 
| 669 |  |  |  |  |  |  |  | 
| 670 |  |  |  |  |  |  | # this adds defaults to $arg_hash as a side effect! | 
| 671 | 277 | 100 |  |  |  | 5423 | ${*$self}{'_SSL_ctx'} = IO::Socket::SSL::SSL_Context->new($arg_hash) | 
|  | 277 |  |  |  |  | 1577 |  | 
| 672 |  |  |  |  |  |  | or return; | 
| 673 |  |  |  |  |  |  |  | 
| 674 | 273 |  |  |  |  | 1019 | return $self; | 
| 675 |  |  |  |  |  |  | } | 
| 676 |  |  |  |  |  |  |  | 
| 677 |  |  |  |  |  |  |  | 
| 678 |  |  |  |  |  |  | sub _skip_rw_error { | 
| 679 | 110 |  |  | 110 |  | 510 | my ($self,$ssl,$rv) = @_; | 
| 680 | 110 |  |  |  |  | 682 | my $err = Net::SSLeay::get_error($ssl,$rv); | 
| 681 | 110 | 100 |  |  |  | 614 | if ( $err == $Net_SSLeay_ERROR_WANT_READ) { | 
|  |  | 100 |  |  |  |  |  | 
| 682 | 71 |  |  |  |  | 350 | $SSL_ERROR = SSL_WANT_READ; | 
| 683 |  |  |  |  |  |  | } elsif ( $err == $Net_SSLeay_ERROR_WANT_WRITE) { | 
| 684 | 2 |  |  |  |  | 23 | $SSL_ERROR = SSL_WANT_WRITE; | 
| 685 |  |  |  |  |  |  | } else { | 
| 686 | 37 |  |  |  |  | 271 | return $err; | 
| 687 |  |  |  |  |  |  | } | 
| 688 | 73 |  | 50 |  |  | 908 | $! ||= EWOULDBLOCK; | 
| 689 | 73 | 50 |  |  |  | 482 | ${*$self}{_SSL_last_err} = [$SSL_ERROR,4] if ref($self); | 
|  | 73 |  |  |  |  | 601 |  | 
| 690 | 73 |  |  |  |  | 447 | Net::SSLeay::ERR_clear_error(); | 
| 691 | 73 |  |  |  |  | 440 | return 0; | 
| 692 |  |  |  |  |  |  | } | 
| 693 |  |  |  |  |  |  |  | 
| 694 |  |  |  |  |  |  |  | 
| 695 |  |  |  |  |  |  | # Call to connect occurs when a new client socket is made using IO::Socket::* | 
| 696 |  |  |  |  |  |  | sub connect { | 
| 697 | 74 |  | 50 | 74 | 1 | 8285 | my $self = shift || return _invalid_object(); | 
| 698 | 74 | 50 |  |  |  | 227 | return $self if ${*$self}{'_SSL_opened'};  # already connected | 
|  | 74 |  |  |  |  | 430 |  | 
| 699 |  |  |  |  |  |  |  | 
| 700 | 74 | 50 |  |  |  | 274 | if ( ! ${*$self}{'_SSL_opening'} ) { | 
|  | 74 |  |  |  |  | 351 |  | 
| 701 |  |  |  |  |  |  | # call SUPER::connect if the underlying socket is not connected | 
| 702 |  |  |  |  |  |  | # if this fails this might not be an error (e.g. if $! = EINPROGRESS | 
| 703 |  |  |  |  |  |  | # and socket is nonblocking this is normal), so keep any error | 
| 704 |  |  |  |  |  |  | # handling to the client | 
| 705 | 74 | 50 |  |  |  | 372 | $DEBUG>=2 && DEBUG('socket not yet connected' ); | 
| 706 | 74 | 50 |  |  |  | 1244 | $self->SUPER::connect(@_) || return; | 
| 707 | 74 | 50 |  |  |  | 11353 | $DEBUG>=2 && DEBUG('socket connected' ); | 
| 708 |  |  |  |  |  |  |  | 
| 709 |  |  |  |  |  |  | # IO::Socket works around systems, which return EISCONN or similar | 
| 710 |  |  |  |  |  |  | # on non-blocking re-connect by returning true, even if $! is set | 
| 711 |  |  |  |  |  |  | # but it does not clear $!, so do it here | 
| 712 | 74 |  |  |  |  | 543 | $! = undef; | 
| 713 |  |  |  |  |  |  |  | 
| 714 |  |  |  |  |  |  | # don't continue with connect_SSL if SSL_startHandshake is set to 0 | 
| 715 | 74 |  |  |  |  | 253 | my $sh = ${*$self}{_SSL_arguments}{SSL_startHandshake}; | 
|  | 74 |  |  |  |  | 450 |  | 
| 716 | 74 | 100 | 66 |  |  | 522 | return $self if defined $sh && ! $sh; | 
| 717 |  |  |  |  |  |  | } | 
| 718 | 62 |  |  |  |  | 758 | return $self->connect_SSL; | 
| 719 |  |  |  |  |  |  | } | 
| 720 |  |  |  |  |  |  |  | 
| 721 |  |  |  |  |  |  |  | 
| 722 |  |  |  |  |  |  | sub connect_SSL { | 
| 723 | 182 |  |  | 182 | 1 | 5022412 | my $self = shift; | 
| 724 | 182 | 100 | 50 |  |  | 1854 | my $args = @_>1 ? {@_}: $_[0]||{}; | 
| 725 | 182 | 50 |  |  |  | 427 | return $self if ${*$self}{'_SSL_opened'};  # already connected | 
|  | 182 |  |  |  |  | 890 |  | 
| 726 |  |  |  |  |  |  |  | 
| 727 | 182 |  |  |  |  | 541 | my ($ssl,$ctx); | 
| 728 | 182 | 100 |  |  |  | 388 | if ( ! ${*$self}{'_SSL_opening'} ) { | 
|  | 182 |  |  |  |  | 724 |  | 
| 729 |  |  |  |  |  |  | # start ssl connection | 
| 730 | 178 | 50 |  |  |  | 716 | $DEBUG>=2 && DEBUG('ssl handshake not started' ); | 
| 731 | 178 |  |  |  |  | 324 | ${*$self}{'_SSL_opening'} = 1; | 
|  | 178 |  |  |  |  | 603 |  | 
| 732 | 178 |  |  |  |  | 373 | my $arg_hash = ${*$self}{'_SSL_arguments'}; | 
|  | 178 |  |  |  |  | 427 |  | 
| 733 |  |  |  |  |  |  |  | 
| 734 | 178 |  |  |  |  | 544 | my $fileno = ${*$self}{'_SSL_fileno'} = fileno($self); | 
|  | 178 |  |  |  |  | 763 |  | 
| 735 | 178 | 50 |  |  |  | 646 | return $self->_internal_error("Socket has no fileno",9) | 
| 736 |  |  |  |  |  |  | if ! defined $fileno; | 
| 737 |  |  |  |  |  |  |  | 
| 738 | 178 |  |  |  |  | 351 | $ctx = ${*$self}{'_SSL_ctx'};  # Reference to real context | 
|  | 178 |  |  |  |  | 597 |  | 
| 739 | 178 |  |  |  |  | 719 | $ssl = ${*$self}{'_SSL_object'} = Net::SSLeay::new($ctx->{context}) | 
| 740 | 178 |  | 50 |  |  | 2767 | || return $self->error("SSL structure creation failed"); | 
| 741 | 178 | 50 |  |  |  | 594 | $CREATED_IN_THIS_THREAD{$ssl} = 1 if $use_threads; | 
| 742 | 178 |  |  |  |  | 1023 | $SSL_OBJECT{$ssl} = [$self,0]; | 
| 743 | 178 |  |  |  |  | 1544 | weaken($SSL_OBJECT{$ssl}[0]); | 
| 744 |  |  |  |  |  |  |  | 
| 745 | 178 | 100 |  |  |  | 681 | if ($ctx->{session_cache}) { | 
| 746 | 12 |  | 66 |  |  | 40 | $arg_hash->{SSL_session_key} ||= do { | 
| 747 |  |  |  |  |  |  | my $host = $arg_hash->{PeerAddr} || $arg_hash->{PeerHost} | 
| 748 | 6 |  | 66 |  |  | 48 | || $self->_update_peer; | 
| 749 | 6 |  | 66 |  |  | 21 | my $port = $arg_hash->{PeerPort} || $arg_hash->{PeerService}; | 
| 750 | 6 | 50 |  |  |  | 36 | $port ? "$host:$port" : $host; | 
| 751 |  |  |  |  |  |  | } | 
| 752 |  |  |  |  |  |  | } | 
| 753 |  |  |  |  |  |  |  | 
| 754 | 178 | 50 |  |  |  | 1623 | Net::SSLeay::set_fd($ssl, $fileno) | 
| 755 |  |  |  |  |  |  | || return $self->error("SSL filehandle association failed"); | 
| 756 |  |  |  |  |  |  |  | 
| 757 | 178 | 50 | 33 |  |  | 1277 | set_msg_callback($self) if $DEBUG>=2 || ${*$self}{_SSL_msg_callback}; | 
|  | 178 |  |  |  |  | 1108 |  | 
| 758 |  |  |  |  |  |  |  | 
| 759 | 178 | 50 |  |  |  | 637 | if ( $can_client_sni ) { | 
|  |  | 0 |  |  |  |  |  | 
| 760 | 178 |  |  |  |  | 348 | my $host; | 
| 761 | 178 | 100 | 100 |  |  | 1649 | if ( exists $arg_hash->{SSL_hostname} ) { | 
|  |  | 100 |  |  |  |  |  | 
| 762 |  |  |  |  |  |  | # explicitly given | 
| 763 |  |  |  |  |  |  | # can be set to undef/'' to not use extension | 
| 764 |  |  |  |  |  |  | $host = $arg_hash->{SSL_hostname} | 
| 765 | 24 |  |  |  |  | 64 | } elsif ( $host = $arg_hash->{PeerAddr} || $arg_hash->{PeerHost} ) { | 
| 766 |  |  |  |  |  |  | # implicitly given | 
| 767 | 62 |  |  |  |  | 441 | $host =~s{:[a-zA-Z0-9_\-]+$}{}; | 
| 768 |  |  |  |  |  |  | # should be hostname, not IPv4/6 | 
| 769 | 62 | 50 | 33 |  |  | 426 | $host = undef if $host !~m{[a-z_]}i or $host =~m{:}; | 
| 770 |  |  |  |  |  |  | } | 
| 771 |  |  |  |  |  |  | # define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 | 
| 772 |  |  |  |  |  |  | # define TLSEXT_NAMETYPE_host_name 0 | 
| 773 | 178 | 100 |  |  |  | 560 | if ($host) { | 
| 774 | 24 | 50 |  |  |  | 70 | $DEBUG>=2 && DEBUG("using SNI with hostname $host"); | 
| 775 | 24 |  |  |  |  | 182 | Net::SSLeay::ctrl($ssl,55,0,$host); | 
| 776 |  |  |  |  |  |  | } else { | 
| 777 | 154 | 50 |  |  |  | 488 | $DEBUG>=2 && DEBUG("not using SNI because hostname is unknown"); | 
| 778 |  |  |  |  |  |  | } | 
| 779 |  |  |  |  |  |  | } elsif ( $arg_hash->{SSL_hostname} ) { | 
| 780 | 0 |  |  |  |  | 0 | return $self->_internal_error( | 
| 781 |  |  |  |  |  |  | "Client side SNI not supported for this openssl",9); | 
| 782 |  |  |  |  |  |  | } else { | 
| 783 | 0 | 0 |  |  |  | 0 | $DEBUG>=2 && DEBUG("not using SNI because openssl is too old"); | 
| 784 |  |  |  |  |  |  | } | 
| 785 |  |  |  |  |  |  |  | 
| 786 | 178 | 100 | 100 |  |  | 1887 | $arg_hash->{PeerAddr} || $arg_hash->{PeerHost} || $self->_update_peer; | 
| 787 | 178 | 100 |  |  |  | 668 | if ( $ctx->{verify_name_ref} ) { | 
| 788 |  |  |  |  |  |  | # need target name for update | 
| 789 |  |  |  |  |  |  | my $host = $arg_hash->{SSL_verifycn_name} | 
| 790 | 103 |  | 100 |  |  | 416 | || $arg_hash->{SSL_hostname}; | 
| 791 | 103 | 100 |  |  |  | 257 | if ( ! defined $host ) { | 
| 792 | 47 | 50 | 66 |  |  | 242 | if ( $host = $arg_hash->{PeerAddr} || $arg_hash->{PeerHost} ) { | 
| 793 | 47 |  |  |  |  | 499 | $host =~s{^ | 
| 794 |  |  |  |  |  |  | ( | 
| 795 |  |  |  |  |  |  | (?:[^:\[]+) |    # ipv4|host | 
| 796 |  |  |  |  |  |  | (?:\[(?:.*)\])   # [ipv6|host] | 
| 797 |  |  |  |  |  |  | ) | 
| 798 |  |  |  |  |  |  | (:[\w\-]+)?          # optional :port | 
| 799 |  |  |  |  |  |  | $}{$1}x;                 # ipv4|host|ipv6 | 
| 800 |  |  |  |  |  |  | } | 
| 801 |  |  |  |  |  |  | } | 
| 802 | 103 |  |  |  |  | 204 | ${$ctx->{verify_name_ref}} = $host; | 
|  | 103 |  |  |  |  | 304 |  | 
| 803 |  |  |  |  |  |  | } | 
| 804 |  |  |  |  |  |  |  | 
| 805 | 178 |  |  |  |  | 463 | my $ocsp = $ctx->{ocsp_mode}; | 
| 806 | 178 | 100 |  |  |  | 1291 | if ( $ocsp & SSL_OCSP_NO_STAPLE ) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 807 |  |  |  |  |  |  | # don't try stapling | 
| 808 |  |  |  |  |  |  | } elsif ( ! $can_ocsp_staple ) { | 
| 809 | 0 | 0 |  |  |  | 0 | croak("OCSP stapling not support") if $ocsp & SSL_OCSP_MUST_STAPLE; | 
| 810 |  |  |  |  |  |  | } elsif ( $ocsp & (SSL_OCSP_TRY_STAPLE|SSL_OCSP_MUST_STAPLE)) { | 
| 811 |  |  |  |  |  |  | # staple by default if verification enabled | 
| 812 | 99 |  |  |  |  | 174 | ${*$self}{_SSL_ocsp_verify} = undef; | 
|  | 99 |  |  |  |  | 355 |  | 
| 813 | 99 |  |  |  |  | 3254 | Net::SSLeay::set_tlsext_status_type($ssl, | 
| 814 |  |  |  |  |  |  | Net::SSLeay::TLSEXT_STATUSTYPE_ocsp()); | 
| 815 | 99 | 50 |  |  |  | 6639 | $DEBUG>=2 && DEBUG("request OCSP stapling"); | 
| 816 |  |  |  |  |  |  | } | 
| 817 |  |  |  |  |  |  |  | 
| 818 | 178 | 100 | 100 |  |  | 816 | if ($ctx->{session_cache} and my $session = | 
| 819 |  |  |  |  |  |  | $ctx->{session_cache}->get_session($arg_hash->{SSL_session_key}) | 
| 820 |  |  |  |  |  |  | ) { | 
| 821 | 8 |  |  |  |  | 33 | Net::SSLeay::set_session($ssl, $session); | 
| 822 |  |  |  |  |  |  | } | 
| 823 |  |  |  |  |  |  | } | 
| 824 |  |  |  |  |  |  |  | 
| 825 | 182 |  | 66 |  |  | 730 | $ssl ||= ${*$self}{'_SSL_object'}; | 
|  | 4 |  |  |  |  | 25 |  | 
| 826 |  |  |  |  |  |  |  | 
| 827 | 182 |  |  |  |  | 1726 | $SSL_ERROR = $! = undef; | 
| 828 |  |  |  |  |  |  | my $timeout = exists $args->{Timeout} | 
| 829 |  |  |  |  |  |  | ? $args->{Timeout} | 
| 830 | 182 | 100 |  |  |  | 647 | : ${*$self}{io_socket_timeout}; # from IO::Socket | 
|  | 180 |  |  |  |  | 651 |  | 
| 831 | 182 | 100 | 66 |  |  | 1008 | if ( defined($timeout) && $timeout>0 && $self->blocking(0) ) { | 
|  |  |  | 66 |  |  |  |  | 
| 832 | 23 | 50 |  |  |  | 567 | $DEBUG>=2 && DEBUG( "set socket to non-blocking to enforce timeout=$timeout" ); | 
| 833 |  |  |  |  |  |  | # timeout was given and socket was blocking | 
| 834 |  |  |  |  |  |  | # enforce timeout with now non-blocking socket | 
| 835 |  |  |  |  |  |  | } else { | 
| 836 |  |  |  |  |  |  | # timeout does not apply because invalid or socket non-blocking | 
| 837 | 159 |  |  |  |  | 380 | $timeout = undef; | 
| 838 | 159 | 50 |  |  |  | 491 | $auto_retry && $auto_retry->($ssl,$self->blocking); | 
| 839 |  |  |  |  |  |  | } | 
| 840 |  |  |  |  |  |  |  | 
| 841 | 182 |  | 66 |  |  | 655 | my $start = defined($timeout) && time(); | 
| 842 |  |  |  |  |  |  | { | 
| 843 | 182 |  |  |  |  | 336 | $SSL_ERROR = undef; | 
|  | 229 |  |  |  |  | 539 |  | 
| 844 | 229 |  |  |  |  | 449 | $CURRENT_SSL_OBJECT = $self; | 
| 845 | 229 | 50 |  |  |  | 618 | $DEBUG>=3 && DEBUG("call Net::SSLeay::connect" ); | 
| 846 | 229 |  |  |  |  | 1963339 | my $rv = Net::SSLeay::connect($ssl); | 
| 847 | 229 |  |  |  |  | 1309 | $CURRENT_SSL_OBJECT = undef; | 
| 848 | 229 | 50 |  |  |  | 1545 | $DEBUG>=3 && DEBUG("done Net::SSLeay::connect -> $rv" ); | 
| 849 | 229 | 100 |  |  |  | 1293 | if ( $rv < 0 ) { | 
|  |  | 50 |  |  |  |  |  | 
| 850 | 84 | 100 |  |  |  | 433 | if ( my $err = $self->_skip_rw_error( $ssl,$rv )) { | 
| 851 | 32 |  |  |  |  | 366 | $self->error("SSL connect attempt failed"); | 
| 852 | 32 |  |  |  |  | 62 | delete ${*$self}{'_SSL_opening'}; | 
|  | 32 |  |  |  |  | 137 |  | 
| 853 | 32 |  |  |  |  | 72 | ${*$self}{'_SSL_opened'} = -1; | 
|  | 32 |  |  |  |  | 100 |  | 
| 854 | 32 | 50 |  |  |  | 144 | $DEBUG>=1 && DEBUG( "fatal SSL error: $SSL_ERROR" ); | 
| 855 | 32 |  |  |  |  | 198 | return $self->fatal_ssl_error(); | 
| 856 |  |  |  |  |  |  | } | 
| 857 |  |  |  |  |  |  |  | 
| 858 | 52 | 50 |  |  |  | 180 | $DEBUG>=2 && DEBUG('ssl handshake in progress' ); | 
| 859 |  |  |  |  |  |  | # connect failed because handshake needs to be completed | 
| 860 |  |  |  |  |  |  | # if socket was non-blocking or no timeout was given return with this error | 
| 861 | 52 | 100 |  |  |  | 193 | return if ! defined($timeout); | 
| 862 |  |  |  |  |  |  |  | 
| 863 |  |  |  |  |  |  | # wait until socket is readable or writable | 
| 864 | 48 |  |  |  |  | 106 | my $rv; | 
| 865 | 48 | 50 |  |  |  | 155 | if ( $timeout>0 ) { | 
| 866 | 48 |  |  |  |  | 113 | my $vec = ''; | 
| 867 | 48 |  |  |  |  | 214 | vec($vec,$self->fileno,1) = 1; | 
| 868 | 48 | 50 |  |  |  | 204 | $DEBUG>=2 && DEBUG( "waiting for fd to become ready: $SSL_ERROR" ); | 
| 869 | 48 | 0 |  |  |  | 5859020 | $rv = | 
|  |  | 50 |  |  |  |  |  | 
| 870 |  |  |  |  |  |  | $SSL_ERROR == SSL_WANT_READ ? select( $vec,undef,undef,$timeout) : | 
| 871 |  |  |  |  |  |  | $SSL_ERROR == SSL_WANT_WRITE ? select( undef,$vec,undef,$timeout) : | 
| 872 |  |  |  |  |  |  | undef; | 
| 873 |  |  |  |  |  |  | } else { | 
| 874 | 0 | 0 |  |  |  | 0 | $DEBUG>=2 && DEBUG("handshake failed because no more time" ); | 
| 875 | 0 |  |  |  |  | 0 | $! = ETIMEDOUT | 
| 876 |  |  |  |  |  |  | } | 
| 877 | 48 | 100 |  |  |  | 550 | if ( ! $rv ) { | 
| 878 | 1 | 50 |  |  |  | 15 | $DEBUG>=2 && DEBUG("handshake failed because socket did not became ready" ); | 
| 879 |  |  |  |  |  |  | # failed because of timeout, return | 
| 880 | 1 |  | 50 |  |  | 32 | $! ||= ETIMEDOUT; | 
| 881 | 1 |  |  |  |  | 6 | delete ${*$self}{'_SSL_opening'}; | 
|  | 1 |  |  |  |  | 24 |  | 
| 882 | 1 |  |  |  |  | 8 | ${*$self}{'_SSL_opened'} = -1; | 
|  | 1 |  |  |  |  | 8 |  | 
| 883 | 1 |  |  |  |  | 20 | $self->blocking(1); # was blocking before | 
| 884 |  |  |  |  |  |  | return | 
| 885 | 1 |  |  |  |  | 67 | } | 
| 886 |  |  |  |  |  |  |  | 
| 887 |  |  |  |  |  |  | # socket is ready, try non-blocking connect again after recomputing timeout | 
| 888 | 47 | 50 |  |  |  | 263 | $DEBUG>=2 && DEBUG("socket ready, retrying connect" ); | 
| 889 | 47 |  |  |  |  | 125 | my $now = time(); | 
| 890 | 47 |  |  |  |  | 181 | $timeout -= $now - $start; | 
| 891 | 47 |  |  |  |  | 103 | $start = $now; | 
| 892 | 47 |  |  |  |  | 158 | redo; | 
| 893 |  |  |  |  |  |  |  | 
| 894 |  |  |  |  |  |  | } elsif ( $rv == 0 ) { | 
| 895 | 0 |  |  |  |  | 0 | delete ${*$self}{'_SSL_opening'}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 896 | 0 | 0 |  |  |  | 0 | $DEBUG>=2 && DEBUG("connection failed - connect returned 0" ); | 
| 897 | 0 |  |  |  |  | 0 | $self->error("SSL connect attempt failed because of handshake problems" ); | 
| 898 | 0 |  |  |  |  | 0 | ${*$self}{'_SSL_opened'} = -1; | 
|  | 0 |  |  |  |  | 0 |  | 
| 899 | 0 |  |  |  |  | 0 | return $self->fatal_ssl_error(); | 
| 900 |  |  |  |  |  |  | } | 
| 901 |  |  |  |  |  |  | } | 
| 902 |  |  |  |  |  |  |  | 
| 903 | 145 | 50 |  |  |  | 463 | $DEBUG>=2 && DEBUG('ssl handshake done' ); | 
| 904 |  |  |  |  |  |  | # ssl connect successful | 
| 905 | 145 |  |  |  |  | 273 | delete ${*$self}{'_SSL_opening'}; | 
|  | 145 |  |  |  |  | 1067 |  | 
| 906 | 145 |  |  |  |  | 432 | ${*$self}{'_SSL_opened'}=1; | 
|  | 145 |  |  |  |  | 469 |  | 
| 907 | 145 | 100 |  |  |  | 544 | if (defined($timeout)) { | 
| 908 | 15 |  |  |  |  | 171 | $self->blocking(1); # reset back to blocking | 
| 909 | 15 |  |  |  |  | 470 | $! = undef; # reset errors from non-blocking | 
| 910 |  |  |  |  |  |  | } | 
| 911 |  |  |  |  |  |  |  | 
| 912 | 145 |  | 66 |  |  | 600 | $ctx ||= ${*$self}{'_SSL_ctx'}; | 
|  | 2 |  |  |  |  | 16 |  | 
| 913 |  |  |  |  |  |  |  | 
| 914 | 145 | 100 |  |  |  | 278 | if ( my $ocsp_result = ${*$self}{_SSL_ocsp_verify} ) { | 
|  | 145 | 50 |  |  |  | 1162 |  | 
| 915 |  |  |  |  |  |  | # got result from OCSP stapling | 
| 916 | 2 | 50 |  |  |  | 31 | if ( $ocsp_result->[0] > 0 ) { | 
|  |  | 0 |  |  |  |  |  | 
| 917 | 2 | 50 |  |  |  | 13 | $DEBUG>=3 && DEBUG("got OCSP success with stapling"); | 
| 918 |  |  |  |  |  |  | # successful validated | 
| 919 |  |  |  |  |  |  | } elsif ( $ocsp_result->[0] < 0 ) { | 
| 920 |  |  |  |  |  |  | # Permanent problem with validation because certificate | 
| 921 |  |  |  |  |  |  | # is either self-signed or the issuer cannot be found. | 
| 922 |  |  |  |  |  |  | # Ignore here, because this will cause other errors too. | 
| 923 | 0 | 0 |  |  |  | 0 | $DEBUG>=3 && DEBUG("got OCSP failure with stapling: %s", | 
| 924 |  |  |  |  |  |  | $ocsp_result->[1]); | 
| 925 |  |  |  |  |  |  | } else { | 
| 926 |  |  |  |  |  |  | # definitely revoked | 
| 927 | 0 | 0 |  |  |  | 0 | $DEBUG>=3 && DEBUG("got OCSP revocation with stapling: %s", | 
| 928 |  |  |  |  |  |  | $ocsp_result->[1]); | 
| 929 | 0 |  |  |  |  | 0 | $self->_internal_error($ocsp_result->[1],5); | 
| 930 | 0 |  |  |  |  | 0 | return $self->fatal_ssl_error(); | 
| 931 |  |  |  |  |  |  | } | 
| 932 |  |  |  |  |  |  | } elsif ( $ctx->{ocsp_mode} & SSL_OCSP_MUST_STAPLE ) { | 
| 933 | 0 |  |  |  |  | 0 | $self->_internal_error("did not receive the required stapled OCSP response",5); | 
| 934 | 0 |  |  |  |  | 0 | return $self->fatal_ssl_error(); | 
| 935 |  |  |  |  |  |  | } | 
| 936 |  |  |  |  |  |  |  | 
| 937 | 145 | 100 | 66 |  |  | 1872 | if (!%sess_cb and $ctx->{session_cache} | 
|  |  |  | 66 |  |  |  |  | 
| 938 |  |  |  |  |  |  | and my $session = Net::SSLeay::get1_session($ssl)) { | 
| 939 |  |  |  |  |  |  | $ctx->{session_cache}->add_session( | 
| 940 | 12 |  |  |  |  | 55 | ${*$self}{_SSL_arguments}{SSL_session_key}, | 
| 941 | 12 |  |  |  |  | 24 | $session | 
| 942 |  |  |  |  |  |  | ); | 
| 943 |  |  |  |  |  |  | } | 
| 944 |  |  |  |  |  |  |  | 
| 945 | 145 |  |  |  |  | 321 | tie *{$self}, "IO::Socket::SSL::SSL_HANDLE", $self; | 
|  | 145 |  |  |  |  | 2002 |  | 
| 946 |  |  |  |  |  |  |  | 
| 947 | 145 |  |  |  |  | 774 | return $self; | 
| 948 |  |  |  |  |  |  | } | 
| 949 |  |  |  |  |  |  |  | 
| 950 |  |  |  |  |  |  | # called if PeerAddr is not set in ${*$self}{'_SSL_arguments'} | 
| 951 |  |  |  |  |  |  | # this can be the case if start_SSL is called with a normal IO::Socket::INET | 
| 952 |  |  |  |  |  |  | # so that PeerAddr|PeerPort are not set from args | 
| 953 |  |  |  |  |  |  | # returns PeerAddr | 
| 954 |  |  |  |  |  |  | sub _update_peer { | 
| 955 | 102 |  |  | 102 |  | 294 | my $self = shift; | 
| 956 | 102 |  |  |  |  | 195 | my $arg_hash = ${*$self}{'_SSL_arguments'}; | 
|  | 102 |  |  |  |  | 530 |  | 
| 957 | 102 |  |  |  |  | 351 | eval { | 
| 958 | 102 |  |  |  |  | 1400 | my $sockaddr = getpeername( $self ); | 
| 959 | 102 |  |  |  |  | 632 | my $af = sockaddr_family($sockaddr); | 
| 960 | 102 | 50 |  |  |  | 383 | if( CAN_IPV6 && $af == AF_INET6 ) { | 
| 961 | 0 |  |  |  |  | 0 | my (undef, $host, $port) = _getnameinfo($sockaddr, | 
| 962 |  |  |  |  |  |  | NI_NUMERICHOST | NI_NUMERICSERV); | 
| 963 | 0 |  |  |  |  | 0 | $arg_hash->{PeerPort} = $port; | 
| 964 | 0 |  |  |  |  | 0 | $arg_hash->{PeerAddr} = $host; | 
| 965 |  |  |  |  |  |  | } else { | 
| 966 | 102 |  |  |  |  | 1320 | my ($port,$addr) = sockaddr_in( $sockaddr); | 
| 967 | 102 |  |  |  |  | 1580 | $arg_hash->{PeerPort} = $port; | 
| 968 | 102 |  |  |  |  | 1130 | $arg_hash->{PeerAddr} = inet_ntoa( $addr ); | 
| 969 |  |  |  |  |  |  | } | 
| 970 |  |  |  |  |  |  | } | 
| 971 |  |  |  |  |  |  | } | 
| 972 |  |  |  |  |  |  |  | 
| 973 |  |  |  |  |  |  | #Call to accept occurs when a new client connects to a server using | 
| 974 |  |  |  |  |  |  | #IO::Socket::SSL | 
| 975 |  |  |  |  |  |  | sub accept { | 
| 976 | 58 |  | 50 | 58 | 1 | 45751 | my $self = shift || return _invalid_object(); | 
| 977 | 58 |  | 50 |  |  | 1932 | my $class = shift || 'IO::Socket::SSL'; | 
| 978 |  |  |  |  |  |  |  | 
| 979 | 58 |  |  |  |  | 304 | my $socket = ${*$self}{'_SSL_opening'}; | 
|  | 58 |  |  |  |  | 1170 |  | 
| 980 | 58 | 50 |  |  |  | 443 | if ( ! $socket ) { | 
| 981 |  |  |  |  |  |  | # underlying socket not done | 
| 982 | 58 | 50 |  |  |  | 412 | $DEBUG>=2 && DEBUG('no socket yet' ); | 
| 983 | 58 |  | 50 |  |  | 1419 | $socket = $self->SUPER::accept($class) || return; | 
| 984 | 58 | 50 |  |  |  | 190740 | $DEBUG>=2 && DEBUG('accept created normal socket '.$socket ); | 
| 985 |  |  |  |  |  |  |  | 
| 986 |  |  |  |  |  |  | # don't continue with accept_SSL if SSL_startHandshake is set to 0 | 
| 987 | 58 |  |  |  |  | 189 | my $sh = ${*$self}{_SSL_arguments}{SSL_startHandshake}; | 
|  | 58 |  |  |  |  | 353 |  | 
| 988 | 58 | 100 | 66 |  |  | 447 | if (defined $sh && ! $sh) { | 
| 989 | 16 |  |  |  |  | 32 | ${*$socket}{_SSL_ctx} = ${*$self}{_SSL_ctx}; | 
|  | 16 |  |  |  |  | 54 |  | 
|  | 16 |  |  |  |  | 52 |  | 
| 990 | 16 |  |  |  |  | 73 | ${*$socket}{_SSL_arguments} = { | 
| 991 | 16 |  |  |  |  | 45 | %{${*$self}{_SSL_arguments}}, | 
|  | 16 |  |  |  |  | 30 |  | 
|  | 16 |  |  |  |  | 413 |  | 
| 992 |  |  |  |  |  |  | SSL_server => 0, | 
| 993 |  |  |  |  |  |  | }; | 
| 994 | 16 | 50 |  |  |  | 69 | $DEBUG>=2 && DEBUG('will not start SSL handshake yet'); | 
| 995 | 16 | 50 |  |  |  | 117 | return wantarray ? ($socket, getpeername($socket) ) : $socket | 
| 996 |  |  |  |  |  |  | } | 
| 997 |  |  |  |  |  |  | } | 
| 998 |  |  |  |  |  |  |  | 
| 999 | 42 | 100 |  |  |  | 416 | $self->accept_SSL($socket) || return; | 
| 1000 | 39 | 50 |  |  |  | 165 | $DEBUG>=2 && DEBUG('accept_SSL ok' ); | 
| 1001 |  |  |  |  |  |  |  | 
| 1002 | 39 | 100 |  |  |  | 250 | return wantarray ? ($socket, getpeername($socket) ) : $socket; | 
| 1003 |  |  |  |  |  |  | } | 
| 1004 |  |  |  |  |  |  |  | 
| 1005 |  |  |  |  |  |  | sub accept_SSL { | 
| 1006 | 122 |  |  | 122 | 1 | 10051753 | my $self = shift; | 
| 1007 | 122 | 100 | 100 |  |  | 1425 | my $socket = ( @_ && UNIVERSAL::isa( $_[0], 'IO::Handle' )) ? shift : $self; | 
| 1008 | 122 | 100 | 50 |  |  | 1130 | my $args = @_>1 ? {@_}: $_[0]||{}; | 
| 1009 |  |  |  |  |  |  |  | 
| 1010 | 122 |  |  |  |  | 404 | my $ssl; | 
| 1011 | 122 | 100 |  |  |  | 257 | if ( ! ${*$self}{'_SSL_opening'} ) { | 
|  | 122 |  |  |  |  | 648 |  | 
| 1012 | 119 | 50 |  |  |  | 490 | $DEBUG>=2 && DEBUG('starting sslifying' ); | 
| 1013 | 119 |  |  |  |  | 278 | ${*$self}{'_SSL_opening'} = $socket; | 
|  | 119 |  |  |  |  | 637 |  | 
| 1014 | 119 | 100 |  |  |  | 592 | if ($socket != $self) { | 
| 1015 | 42 |  |  |  |  | 95 | ${*$socket}{_SSL_ctx} = ${*$self}{_SSL_ctx}; | 
|  | 42 |  |  |  |  | 284 |  | 
|  | 42 |  |  |  |  | 154 |  | 
| 1016 | 42 |  |  |  |  | 193 | ${*$socket}{_SSL_arguments} = { | 
| 1017 | 42 |  |  |  |  | 109 | %{${*$self}{_SSL_arguments}}, | 
|  | 42 |  |  |  |  | 124 |  | 
|  | 42 |  |  |  |  | 2072 |  | 
| 1018 |  |  |  |  |  |  | SSL_server => 0 | 
| 1019 |  |  |  |  |  |  | }; | 
| 1020 |  |  |  |  |  |  | } | 
| 1021 |  |  |  |  |  |  |  | 
| 1022 | 119 |  |  |  |  | 461 | my $fileno = ${*$socket}{'_SSL_fileno'} = fileno($socket); | 
|  | 119 |  |  |  |  | 436 |  | 
| 1023 | 119 | 50 |  |  |  | 498 | return $socket->_internal_error("Socket has no fileno",9) | 
| 1024 |  |  |  |  |  |  | if ! defined $fileno; | 
| 1025 |  |  |  |  |  |  |  | 
| 1026 | 119 |  |  |  |  | 582 | $ssl = ${*$socket}{_SSL_object} = | 
| 1027 |  |  |  |  |  |  | Net::SSLeay::new(${*$socket}{_SSL_ctx}{context}) | 
| 1028 | 119 |  | 50 |  |  | 214 | || return $socket->error("SSL structure creation failed"); | 
| 1029 | 119 | 50 |  |  |  | 489 | $CREATED_IN_THIS_THREAD{$ssl} = 1 if $use_threads; | 
| 1030 | 119 |  |  |  |  | 762 | $SSL_OBJECT{$ssl} = [$socket,1]; | 
| 1031 | 119 |  |  |  |  | 879 | weaken($SSL_OBJECT{$ssl}[0]); | 
| 1032 |  |  |  |  |  |  |  | 
| 1033 | 119 | 50 |  |  |  | 884 | Net::SSLeay::set_fd($ssl, $fileno) | 
| 1034 |  |  |  |  |  |  | || return $socket->error("SSL filehandle association failed"); | 
| 1035 |  |  |  |  |  |  |  | 
| 1036 | 119 | 50 | 33 |  |  | 944 | set_msg_callback($self) if $DEBUG>=2 || ${*$self}{_SSL_msg_callback}; | 
|  | 119 |  |  |  |  | 813 |  | 
| 1037 |  |  |  |  |  |  | } | 
| 1038 |  |  |  |  |  |  |  | 
| 1039 | 122 |  | 66 |  |  | 418 | $ssl ||= ${*$socket}{'_SSL_object'}; | 
|  | 3 |  |  |  |  | 17 |  | 
| 1040 |  |  |  |  |  |  |  | 
| 1041 | 122 |  |  |  |  | 1278 | $SSL_ERROR = $! = undef; | 
| 1042 |  |  |  |  |  |  | #$DEBUG>=2 && DEBUG('calling ssleay::accept' ); | 
| 1043 |  |  |  |  |  |  |  | 
| 1044 |  |  |  |  |  |  | my $timeout = exists $args->{Timeout} | 
| 1045 |  |  |  |  |  |  | ? $args->{Timeout} | 
| 1046 | 122 | 100 |  |  |  | 495 | : ${*$self}{io_socket_timeout}; # from IO::Socket | 
|  | 113 |  |  |  |  | 381 |  | 
| 1047 | 122 | 100 | 66 |  |  | 963 | if ( defined($timeout) && $timeout>0 && $socket->blocking(0) ) { | 
|  |  |  | 66 |  |  |  |  | 
| 1048 |  |  |  |  |  |  | # timeout was given and socket was blocking | 
| 1049 |  |  |  |  |  |  | # enforce timeout with now non-blocking socket | 
| 1050 |  |  |  |  |  |  | } else { | 
| 1051 |  |  |  |  |  |  | # timeout does not apply because invalid or socket non-blocking | 
| 1052 | 108 |  |  |  |  | 216 | $timeout = undef; | 
| 1053 | 108 | 50 |  |  |  | 307 | $auto_retry && $auto_retry->($ssl,$socket->blocking); | 
| 1054 |  |  |  |  |  |  | } | 
| 1055 |  |  |  |  |  |  |  | 
| 1056 | 122 |  | 66 |  |  | 1024 | my $start = defined($timeout) && time(); | 
| 1057 |  |  |  |  |  |  | { | 
| 1058 | 122 |  |  |  |  | 320 | $SSL_ERROR = undef; | 
|  | 136 |  |  |  |  | 317 |  | 
| 1059 | 136 |  |  |  |  | 347 | $CURRENT_SSL_OBJECT = $self; | 
| 1060 | 136 |  |  |  |  | 3117119 | my $rv = Net::SSLeay::accept($ssl); | 
| 1061 | 136 |  |  |  |  | 888 | $CURRENT_SSL_OBJECT = undef; | 
| 1062 | 136 | 50 |  |  |  | 736 | $DEBUG>=3 && DEBUG( "Net::SSLeay::accept -> $rv" ); | 
| 1063 | 136 | 100 |  |  |  | 915 | if ( $rv < 0 ) { | 
|  |  | 100 |  |  |  |  |  | 
| 1064 | 21 | 100 |  |  |  | 332 | if ( my $err = $socket->_skip_rw_error( $ssl,$rv )) { | 
| 1065 | 3 |  |  |  |  | 75 | $socket->error("SSL accept attempt failed"); | 
| 1066 | 3 |  |  |  |  | 8 | delete ${*$self}{'_SSL_opening'}; | 
|  | 3 |  |  |  |  | 31 |  | 
| 1067 | 3 |  |  |  |  | 10 | ${*$socket}{'_SSL_opened'} = -1; | 
|  | 3 |  |  |  |  | 16 |  | 
| 1068 | 3 |  |  |  |  | 33 | return $socket->fatal_ssl_error(); | 
| 1069 |  |  |  |  |  |  | } | 
| 1070 |  |  |  |  |  |  |  | 
| 1071 |  |  |  |  |  |  | # accept failed because handshake needs to be completed | 
| 1072 |  |  |  |  |  |  | # if socket was non-blocking or no timeout was given return with this error | 
| 1073 | 18 | 100 |  |  |  | 94 | return if ! defined($timeout); | 
| 1074 |  |  |  |  |  |  |  | 
| 1075 |  |  |  |  |  |  | # wait until socket is readable or writable | 
| 1076 | 15 |  |  |  |  | 40 | my $rv; | 
| 1077 | 15 | 50 |  |  |  | 56 | if ( $timeout>0 ) { | 
| 1078 | 15 |  |  |  |  | 113 | my $vec = ''; | 
| 1079 | 15 |  |  |  |  | 155 | vec($vec,$socket->fileno,1) = 1; | 
| 1080 | 15 | 0 |  |  |  | 5024455 | $rv = | 
|  |  | 50 |  |  |  |  |  | 
| 1081 |  |  |  |  |  |  | $SSL_ERROR == SSL_WANT_READ  ? select( $vec,undef,undef,$timeout) : | 
| 1082 |  |  |  |  |  |  | $SSL_ERROR == SSL_WANT_WRITE ? select( undef,$vec,undef,$timeout) : | 
| 1083 |  |  |  |  |  |  | undef; | 
| 1084 |  |  |  |  |  |  | } else { | 
| 1085 | 0 |  |  |  |  | 0 | $! = ETIMEDOUT | 
| 1086 |  |  |  |  |  |  | } | 
| 1087 | 15 | 100 |  |  |  | 283 | if ( ! $rv ) { | 
| 1088 |  |  |  |  |  |  | # failed because of timeout, return | 
| 1089 | 1 |  | 50 |  |  | 46 | $! ||= ETIMEDOUT; | 
| 1090 | 1 |  |  |  |  | 4 | delete ${*$self}{'_SSL_opening'}; | 
|  | 1 |  |  |  |  | 53 |  | 
| 1091 | 1 |  |  |  |  | 7 | ${*$socket}{'_SSL_opened'} = -1; | 
|  | 1 |  |  |  |  | 7 |  | 
| 1092 | 1 |  |  |  |  | 36 | $socket->blocking(1); # was blocking before | 
| 1093 |  |  |  |  |  |  | return | 
| 1094 | 1 |  |  |  |  | 76 | } | 
| 1095 |  |  |  |  |  |  |  | 
| 1096 |  |  |  |  |  |  | # socket is ready, try non-blocking accept again after recomputing timeout | 
| 1097 | 14 |  |  |  |  | 59 | my $now = time(); | 
| 1098 | 14 |  |  |  |  | 91 | $timeout -= $now - $start; | 
| 1099 | 14 |  |  |  |  | 27 | $start = $now; | 
| 1100 | 14 |  |  |  |  | 40 | redo; | 
| 1101 |  |  |  |  |  |  |  | 
| 1102 |  |  |  |  |  |  | } elsif ( $rv == 0 ) { | 
| 1103 | 13 |  |  |  |  | 154 | $socket->error("SSL accept attempt failed because of handshake problems" ); | 
| 1104 | 13 |  |  |  |  | 22 | delete ${*$self}{'_SSL_opening'}; | 
|  | 13 |  |  |  |  | 46 |  | 
| 1105 | 13 |  |  |  |  | 29 | ${*$socket}{'_SSL_opened'} = -1; | 
|  | 13 |  |  |  |  | 36 |  | 
| 1106 | 13 |  |  |  |  | 80 | return $socket->fatal_ssl_error(); | 
| 1107 |  |  |  |  |  |  | } | 
| 1108 |  |  |  |  |  |  | } | 
| 1109 |  |  |  |  |  |  |  | 
| 1110 | 102 | 50 |  |  |  | 506 | $DEBUG>=2 && DEBUG('handshake done, socket ready' ); | 
| 1111 |  |  |  |  |  |  | # socket opened | 
| 1112 | 102 |  |  |  |  | 190 | delete ${*$self}{'_SSL_opening'}; | 
|  | 102 |  |  |  |  | 766 |  | 
| 1113 | 102 |  |  |  |  | 349 | ${*$socket}{'_SSL_opened'} = 1; | 
|  | 102 |  |  |  |  | 449 |  | 
| 1114 | 102 | 100 |  |  |  | 389 | if (defined($timeout)) { | 
| 1115 | 12 |  |  |  |  | 80 | $socket->blocking(1); # reset back to blocking | 
| 1116 | 12 |  |  |  |  | 290 | $! = undef; # reset errors from non-blocking | 
| 1117 |  |  |  |  |  |  | } | 
| 1118 |  |  |  |  |  |  |  | 
| 1119 | 102 |  |  |  |  | 211 | tie *{$socket}, "IO::Socket::SSL::SSL_HANDLE", $socket; | 
|  | 102 |  |  |  |  | 2081 |  | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 | 102 |  |  |  |  | 567 | return $socket; | 
| 1122 |  |  |  |  |  |  | } | 
| 1123 |  |  |  |  |  |  |  | 
| 1124 |  |  |  |  |  |  |  | 
| 1125 |  |  |  |  |  |  | # support user defined message callback but also internal debugging | 
| 1126 |  |  |  |  |  |  | sub _msg_callback { | 
| 1127 |  |  |  |  |  |  | ##  my ($direction, $ssl_ver, $content_type, $buf, $len, $ssl, $userp) = @_; | 
| 1128 | 0 | 0 |  | 0 |  | 0 | IO::Socket::SSL::Trace::ossl_trace(@_) if $DEBUG>=2; | 
| 1129 | 0 |  | 0 |  |  | 0 | my $self = ($SSL_OBJECT{$_[5]} || return)->[0] || return; | 
| 1130 | 0 | 0 |  |  |  | 0 | if (my $cb = ${*$self}{_SSL_msg_callback}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 1131 | 0 |  |  |  |  | 0 | my ($sub,@arg) = @$cb; | 
| 1132 | 0 |  |  |  |  | 0 | $sub->($self, @_[0..5], @arg); | 
| 1133 |  |  |  |  |  |  | } | 
| 1134 |  |  |  |  |  |  | } | 
| 1135 |  |  |  |  |  |  |  | 
| 1136 |  |  |  |  |  |  | my $ssleay_set_msg_callback = defined &Net::SSLeay::set_msg_callback | 
| 1137 |  |  |  |  |  |  | && \&Net::SSLeay::set_msg_callback; | 
| 1138 |  |  |  |  |  |  |  | 
| 1139 |  |  |  |  |  |  | sub set_msg_callback { | 
| 1140 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 1141 | 0 | 0 |  |  |  | 0 | if (@_) { | 
| 1142 | 0 | 0 |  |  |  | 0 | if ($_[0]) { | 
| 1143 |  |  |  |  |  |  | # enable user defined callback: ($cb,@arg) | 
| 1144 | 0 | 0 |  |  |  | 0 | die "no support for msg callback with this version of Net::SSLeay/OpenSSL" | 
| 1145 |  |  |  |  |  |  | if !$ssleay_set_msg_callback; | 
| 1146 | 0 |  |  |  |  | 0 | ${*$self}{_SSL_msg_callback} = [@_]; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1147 |  |  |  |  |  |  | } else { | 
| 1148 |  |  |  |  |  |  | # disable user defined callback | 
| 1149 | 0 |  |  |  |  | 0 | delete ${*$self}{_SSL_msg_callback}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1150 |  |  |  |  |  |  | } | 
| 1151 |  |  |  |  |  |  | } | 
| 1152 |  |  |  |  |  |  |  | 
| 1153 |  |  |  |  |  |  | # activate user set callback and/or internal for debugging | 
| 1154 | 0 | 0 | 0 |  |  | 0 | if ($ssleay_set_msg_callback and my $ssl = ${*$self}{_SSL_object}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 1155 |  |  |  |  |  |  | $ssleay_set_msg_callback->($ssl, | 
| 1156 | 0 | 0 | 0 |  |  | 0 | ($DEBUG>=2 || ${*$self}{_SSL_msg_callback})? \&_msg_callback : undef) | 
| 1157 |  |  |  |  |  |  | } | 
| 1158 |  |  |  |  |  |  | } | 
| 1159 |  |  |  |  |  |  |  | 
| 1160 |  |  |  |  |  |  |  | 
| 1161 |  |  |  |  |  |  | ####### I/O subroutines ######################## | 
| 1162 |  |  |  |  |  |  |  | 
| 1163 |  |  |  |  |  |  | if ($auto_retry) { | 
| 1164 |  |  |  |  |  |  | *blocking = sub { | 
| 1165 |  |  |  |  |  |  | my $self = shift; | 
| 1166 |  |  |  |  |  |  | { @_ && $auto_retry->(${*$self}{_SSL_object} || last, @_); } | 
| 1167 |  |  |  |  |  |  | return $self->SUPER::blocking(@_); | 
| 1168 |  |  |  |  |  |  | }; | 
| 1169 |  |  |  |  |  |  | } | 
| 1170 |  |  |  |  |  |  |  | 
| 1171 |  |  |  |  |  |  | sub _generic_read { | 
| 1172 | 6117 |  |  | 6117 |  | 12247 | my ($self, $read_func, undef, $length, $offset) = @_; | 
| 1173 | 6117 |  | 50 |  |  | 7764 | my $ssl =  ${*$self}{_SSL_object} || return; | 
| 1174 | 6117 |  |  |  |  | 9780 | my $buffer=\$_[2]; | 
| 1175 |  |  |  |  |  |  |  | 
| 1176 | 6117 |  |  |  |  | 14348 | $SSL_ERROR = $! = undef; | 
| 1177 | 6117 |  |  |  |  | 635505 | my ($data,$rwerr) = $read_func->($ssl, $length); | 
| 1178 | 6117 |  |  |  |  | 29146 | while ( ! defined($data)) { | 
| 1179 | 1 | 50 |  |  |  | 8 | if ( my $err = $self->_skip_rw_error( $ssl, defined($rwerr) ? $rwerr:-1 )) { | 
|  |  | 50 |  |  |  |  |  | 
| 1180 |  |  |  |  |  |  | # OpenSSL 1.1.0c+ : EOF can now result in SSL_read returning -1 and SSL_ERROR_SYSCALL | 
| 1181 |  |  |  |  |  |  | # OpenSSL 3.0 : EOF can now result in SSL_read returning -1 and SSL_ERROR_SSL | 
| 1182 | 0 | 0 | 0 |  |  | 0 | if (not $! and $err == $Net_SSLeay_ERROR_SSL || $err == $Net_SSLeay_ERROR_SYSCALL) { | 
|  |  |  | 0 |  |  |  |  | 
| 1183 |  |  |  |  |  |  | # treat as EOF | 
| 1184 | 0 |  |  |  |  | 0 | $data = ''; | 
| 1185 | 0 |  |  |  |  | 0 | last; | 
| 1186 |  |  |  |  |  |  | } | 
| 1187 | 0 |  |  |  |  | 0 | $self->error("SSL read error"); | 
| 1188 |  |  |  |  |  |  | } | 
| 1189 | 1 |  |  |  |  | 6 | return; | 
| 1190 |  |  |  |  |  |  | } | 
| 1191 |  |  |  |  |  |  |  | 
| 1192 | 6116 |  |  |  |  | 8688 | $length = length($data); | 
| 1193 | 6116 | 100 |  |  |  | 12522 | $$buffer = '' if !defined $$buffer; | 
| 1194 | 6116 |  | 100 |  |  | 20016 | $offset ||= 0; | 
| 1195 | 6116 | 100 |  |  |  | 11096 | if ($offset>length($$buffer)) { | 
| 1196 | 1 |  |  |  |  | 17 | $$buffer.="\0" x ($offset-length($$buffer));  #mimic behavior of read | 
| 1197 |  |  |  |  |  |  | } | 
| 1198 |  |  |  |  |  |  |  | 
| 1199 | 6116 |  |  |  |  | 9974 | substr($$buffer, $offset, length($$buffer), $data); | 
| 1200 | 6116 |  |  |  |  | 22385 | return $length; | 
| 1201 |  |  |  |  |  |  | } | 
| 1202 |  |  |  |  |  |  |  | 
| 1203 |  |  |  |  |  |  | sub read { | 
| 1204 | 6 |  |  | 6 | 0 | 377 | my $self = shift; | 
| 1205 | 6 | 100 |  |  |  | 13 | ${*$self}{_SSL_object} && return _generic_read($self, | 
|  | 6 | 50 |  |  |  | 118 |  | 
| 1206 |  |  |  |  |  |  | $self->blocking ? \&Net::SSLeay::ssl_read_all : \&Net::SSLeay::read, | 
| 1207 |  |  |  |  |  |  | @_ | 
| 1208 |  |  |  |  |  |  | ); | 
| 1209 |  |  |  |  |  |  |  | 
| 1210 |  |  |  |  |  |  | # fall back to plain read if we are not required to use SSL yet | 
| 1211 | 0 |  |  |  |  | 0 | return $self->SUPER::read(@_); | 
| 1212 |  |  |  |  |  |  | } | 
| 1213 |  |  |  |  |  |  |  | 
| 1214 |  |  |  |  |  |  | # contrary to the behavior of read sysread can read partial data | 
| 1215 |  |  |  |  |  |  | sub sysread { | 
| 1216 | 6110 |  |  | 6110 | 1 | 8983 | my $self = shift; | 
| 1217 | 6110 | 50 |  |  |  | 8092 | ${*$self}{_SSL_object} && return _generic_read( $self, | 
|  | 6110 |  |  |  |  | 21314 |  | 
| 1218 |  |  |  |  |  |  | \&Net::SSLeay::read, @_ ); | 
| 1219 |  |  |  |  |  |  |  | 
| 1220 |  |  |  |  |  |  | # fall back to plain sysread if we are not required to use SSL yet | 
| 1221 | 0 |  |  |  |  | 0 | my $rv = $self->SUPER::sysread(@_); | 
| 1222 | 0 |  |  |  |  | 0 | return $rv; | 
| 1223 |  |  |  |  |  |  | } | 
| 1224 |  |  |  |  |  |  |  | 
| 1225 |  |  |  |  |  |  | sub peek { | 
| 1226 | 6 |  |  | 6 | 1 | 4317 | my $self = shift; | 
| 1227 | 6 | 100 |  |  |  | 13 | ${*$self}{_SSL_object} && return _generic_read( $self, | 
|  | 6 |  |  |  |  | 45 |  | 
| 1228 |  |  |  |  |  |  | \&Net::SSLeay::peek, @_ ); | 
| 1229 |  |  |  |  |  |  |  | 
| 1230 |  |  |  |  |  |  | # fall back to plain peek if we are not required to use SSL yet | 
| 1231 |  |  |  |  |  |  | # emulate peek with recv(...,MS_PEEK) - peek(buf,len,offset) | 
| 1232 | 5 | 50 |  |  |  | 75 | return if ! defined recv($self,my $buf,$_[1],MSG_PEEK); | 
| 1233 | 5 | 50 |  |  |  | 28 | $_[0] = $_[2] ? substr($_[0],0,$_[2]).$buf : $buf; | 
| 1234 | 5 |  |  |  |  | 13 | return length($buf); | 
| 1235 |  |  |  |  |  |  | } | 
| 1236 |  |  |  |  |  |  |  | 
| 1237 |  |  |  |  |  |  |  | 
| 1238 |  |  |  |  |  |  | sub _generic_write { | 
| 1239 | 7229 |  |  | 7229 |  | 15311 | my ($self, $write_all, undef, $length, $offset) = @_; | 
| 1240 |  |  |  |  |  |  |  | 
| 1241 | 7229 |  | 50 |  |  | 9769 | my $ssl =  ${*$self}{_SSL_object} || return; | 
| 1242 | 7229 |  |  |  |  | 12573 | my $buffer = \$_[2]; | 
| 1243 |  |  |  |  |  |  |  | 
| 1244 | 7229 |  |  |  |  | 9856 | my $buf_len = length($$buffer); | 
| 1245 | 7229 |  | 66 |  |  | 12741 | $length ||= $buf_len; | 
| 1246 | 7229 |  | 100 |  |  | 24233 | $offset ||= 0; | 
| 1247 | 7229 | 50 |  |  |  | 12901 | return $self->_internal_error("Invalid offset for SSL write",9) | 
| 1248 |  |  |  |  |  |  | if $offset>$buf_len; | 
| 1249 | 7229 | 50 |  |  |  | 11656 | return 0 if ($offset == $buf_len); | 
| 1250 |  |  |  |  |  |  |  | 
| 1251 | 7229 |  |  |  |  | 18027 | $SSL_ERROR = $! = undef; | 
| 1252 | 7229 |  |  |  |  | 9252 | my $written; | 
| 1253 | 7229 | 100 |  |  |  | 11372 | if ( $write_all ) { | 
| 1254 | 59 | 50 |  |  |  | 220 | my $data = $length < $buf_len-$offset ? substr($$buffer, $offset, $length) : $$buffer; | 
| 1255 | 59 |  |  |  |  | 2331 | ($written, my $errs) = Net::SSLeay::ssl_write_all($ssl, $data); | 
| 1256 |  |  |  |  |  |  | # ssl_write_all returns number of bytes written | 
| 1257 | 59 | 50 | 33 |  |  | 41563 | $written = undef if ! $written && $errs; | 
| 1258 |  |  |  |  |  |  | } else { | 
| 1259 | 7170 |  |  |  |  | 99555 | $written = Net::SSLeay::write_partial( $ssl,$offset,$length,$$buffer ); | 
| 1260 |  |  |  |  |  |  | # write_partial does SSL_write which returns -1 on error | 
| 1261 | 7170 | 100 |  |  |  | 20982 | $written = undef if $written <= 0; | 
| 1262 |  |  |  |  |  |  | } | 
| 1263 | 7229 | 100 |  |  |  | 14451 | if ( !defined($written) ) { | 
| 1264 | 4 | 100 |  |  |  | 61 | if ( my $err = $self->_skip_rw_error( $ssl,-1 )) { | 
| 1265 |  |  |  |  |  |  | # if $! is not set with ERROR_SYSCALL then report as EPIPE | 
| 1266 | 2 | 50 | 50 |  |  | 90 | $! ||= EPIPE if $err == $Net_SSLeay_ERROR_SYSCALL; | 
| 1267 | 2 |  |  |  |  | 62 | $self->error("SSL write error ($err)"); | 
| 1268 |  |  |  |  |  |  | } | 
| 1269 | 4 |  |  |  |  | 27 | return; | 
| 1270 |  |  |  |  |  |  | } | 
| 1271 |  |  |  |  |  |  |  | 
| 1272 | 7225 |  |  |  |  | 30523 | return $written; | 
| 1273 |  |  |  |  |  |  | } | 
| 1274 |  |  |  |  |  |  |  | 
| 1275 |  |  |  |  |  |  | # if socket is blocking write() should return only on error or | 
| 1276 |  |  |  |  |  |  | # if all data are written | 
| 1277 |  |  |  |  |  |  | sub write { | 
| 1278 | 60 |  |  | 60 | 1 | 406 | my $self = shift; | 
| 1279 | 60 | 50 |  |  |  | 105 | ${*$self}{_SSL_object} && return _generic_write( $self, | 
|  | 60 |  |  |  |  | 702 |  | 
| 1280 |  |  |  |  |  |  | scalar($self->blocking),@_ ); | 
| 1281 |  |  |  |  |  |  |  | 
| 1282 |  |  |  |  |  |  | # fall back to plain write if we are not required to use SSL yet | 
| 1283 | 0 |  |  |  |  | 0 | return $self->SUPER::write(@_); | 
| 1284 |  |  |  |  |  |  | } | 
| 1285 |  |  |  |  |  |  |  | 
| 1286 |  |  |  |  |  |  | # contrary to write syswrite() returns already if only | 
| 1287 |  |  |  |  |  |  | # a part of the data is written | 
| 1288 |  |  |  |  |  |  | sub syswrite { | 
| 1289 | 7169 |  |  | 7169 | 1 | 10110 | my $self = shift; | 
| 1290 | 7169 | 50 |  |  |  | 8739 | ${*$self}{_SSL_object} && return _generic_write($self,0,@_); | 
|  | 7169 |  |  |  |  | 22872 |  | 
| 1291 |  |  |  |  |  |  |  | 
| 1292 |  |  |  |  |  |  | # fall back to plain syswrite if we are not required to use SSL yet | 
| 1293 | 0 |  |  |  |  | 0 | return $self->SUPER::syswrite(@_); | 
| 1294 |  |  |  |  |  |  | } | 
| 1295 |  |  |  |  |  |  |  | 
| 1296 |  |  |  |  |  |  | sub print { | 
| 1297 | 57 |  |  | 57 | 0 | 304253 | my $self = shift; | 
| 1298 | 57 |  | 50 |  |  | 885 | my $string = join(($, or ''), @_, ($\ or '')); | 
|  |  |  | 50 |  |  |  |  | 
| 1299 | 57 |  |  |  |  | 310 | return $self->write( $string ); | 
| 1300 |  |  |  |  |  |  | } | 
| 1301 |  |  |  |  |  |  |  | 
| 1302 |  |  |  |  |  |  | sub printf { | 
| 1303 | 2 |  |  | 2 | 0 | 20 | my ($self,$format) = (shift,shift); | 
| 1304 | 2 |  |  |  |  | 71 | return $self->write(sprintf($format, @_)); | 
| 1305 |  |  |  |  |  |  | } | 
| 1306 |  |  |  |  |  |  |  | 
| 1307 |  |  |  |  |  |  | sub getc { | 
| 1308 | 2 |  |  | 2 | 0 | 970 | my ($self, $buffer) = (shift, undef); | 
| 1309 | 2 | 50 |  |  |  | 9 | return $buffer if $self->read($buffer, 1, 0); | 
| 1310 |  |  |  |  |  |  | } | 
| 1311 |  |  |  |  |  |  |  | 
| 1312 |  |  |  |  |  |  | sub readline { | 
| 1313 | 83 |  |  | 83 | 0 | 196 | my $self = shift; | 
| 1314 | 83 | 50 |  |  |  | 156 | ${*$self}{_SSL_object} or return $self->SUPER::getline; | 
|  | 83 |  |  |  |  | 403 |  | 
| 1315 |  |  |  |  |  |  |  | 
| 1316 | 83 | 100 | 100 |  |  | 790 | if ( not defined $/ or wantarray) { | 
| 1317 |  |  |  |  |  |  | # read all and split | 
| 1318 |  |  |  |  |  |  |  | 
| 1319 | 7 |  |  |  |  | 69 | my $buf = ''; | 
| 1320 | 7 |  |  |  |  | 18 | while (1) { | 
| 1321 | 14 |  |  |  |  | 75 | my $rv = $self->sysread($buf,2**16,length($buf)); | 
| 1322 | 14 | 50 |  |  |  | 86 | if ( ! defined $rv ) { | 
|  |  | 100 |  |  |  |  |  | 
| 1323 | 0 | 0 |  |  |  | 0 | next if $! == EINTR;       # retry | 
| 1324 | 0 | 0 | 0 |  |  | 0 | last if $! == EWOULDBLOCK || $! == EAGAIN; # use everything so far | 
| 1325 | 0 |  |  |  |  | 0 | return;                    # return error | 
| 1326 |  |  |  |  |  |  | } elsif ( ! $rv ) { | 
| 1327 |  |  |  |  |  |  | last | 
| 1328 | 7 |  |  |  |  | 35 | } | 
| 1329 |  |  |  |  |  |  | } | 
| 1330 |  |  |  |  |  |  |  | 
| 1331 | 7 | 100 |  |  |  | 96 | if ( ! defined $/ ) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 1332 | 2 |  |  |  |  | 28 | return $buf | 
| 1333 |  |  |  |  |  |  | } elsif ( ref($/)) { | 
| 1334 | 1 |  |  |  |  | 7 | my $size = ${$/}; | 
|  | 1 |  |  |  |  | 6 |  | 
| 1335 | 1 | 50 |  |  |  | 10 | die "bad value in ref \$/: $size" unless $size>0; | 
| 1336 | 1 |  |  |  |  | 76 | return $buf=~m{\G(.{1,$size})}g; | 
| 1337 |  |  |  |  |  |  | } elsif ( $/ eq '' ) { | 
| 1338 | 1 |  |  |  |  | 31 | return $buf =~m{\G(.*\n\n+|.+)}g; | 
| 1339 |  |  |  |  |  |  | } else { | 
| 1340 | 3 |  |  |  |  | 304 | return $buf =~m{\G(.*$/|.+)}g; | 
| 1341 |  |  |  |  |  |  | } | 
| 1342 |  |  |  |  |  |  | } | 
| 1343 |  |  |  |  |  |  |  | 
| 1344 |  |  |  |  |  |  | # read only one line | 
| 1345 | 76 | 100 |  |  |  | 232 | if ( ref($/) ) { | 
| 1346 | 1 |  |  |  |  | 5 | my $size = ${$/}; | 
|  | 1 |  |  |  |  | 12 |  | 
| 1347 |  |  |  |  |  |  | # read record of $size bytes | 
| 1348 | 1 | 50 |  |  |  | 7 | die "bad value in ref \$/: $size" unless $size>0; | 
| 1349 | 1 |  |  |  |  | 3 | my $buf = ''; | 
| 1350 | 1 |  |  |  |  | 5 | while ( $size>length($buf)) { | 
| 1351 | 1 |  |  |  |  | 6 | my $rv = $self->sysread($buf,$size-length($buf),length($buf)); | 
| 1352 | 1 | 50 |  |  |  | 21 | if ( ! defined $rv ) { | 
|  |  | 50 |  |  |  |  |  | 
| 1353 | 0 | 0 |  |  |  | 0 | next if $! == EINTR;       # retry | 
| 1354 | 0 | 0 | 0 |  |  | 0 | last if $! == EWOULDBLOCK || $! == EAGAIN; # use everything so far | 
| 1355 | 0 |  |  |  |  | 0 | return;                    # return error | 
| 1356 |  |  |  |  |  |  | } elsif ( ! $rv ) { | 
| 1357 |  |  |  |  |  |  | last | 
| 1358 | 0 |  |  |  |  | 0 | } | 
| 1359 |  |  |  |  |  |  | } | 
| 1360 | 1 |  |  |  |  | 7 | return $buf; | 
| 1361 |  |  |  |  |  |  | } | 
| 1362 |  |  |  |  |  |  |  | 
| 1363 | 75 | 100 |  |  |  | 579 | my ($delim0,$delim1) = $/ eq '' ? ("\n\n","\n"):($/,''); | 
| 1364 |  |  |  |  |  |  |  | 
| 1365 |  |  |  |  |  |  | # find first occurrence of $delim0 followed by as much as possible $delim1 | 
| 1366 | 75 |  |  |  |  | 224 | my $buf = ''; | 
| 1367 | 75 |  |  |  |  | 184 | my $eod = 0;  # pointer into $buf after $delim0 $delim1* | 
| 1368 | 75 | 50 |  |  |  | 256 | my $ssl = $self->_get_ssl_object or return; | 
| 1369 | 75 |  |  |  |  | 154 | while (1) { | 
| 1370 |  |  |  |  |  |  |  | 
| 1371 |  |  |  |  |  |  | # wait until we have more data or eof | 
| 1372 | 79 |  |  |  |  | 2544014 | my $poke = Net::SSLeay::peek($ssl,1); | 
| 1373 | 79 | 100 | 100 |  |  | 1251 | if ( ! defined $poke or $poke eq '' ) { | 
| 1374 | 21 | 100 |  |  |  | 209 | next if $! == EINTR; | 
| 1375 |  |  |  |  |  |  | } | 
| 1376 |  |  |  |  |  |  |  | 
| 1377 | 78 |  |  |  |  | 185 | my $skip = 0; | 
| 1378 |  |  |  |  |  |  |  | 
| 1379 |  |  |  |  |  |  | # peek into available data w/o reading | 
| 1380 | 78 |  |  |  |  | 390 | my $pending = Net::SSLeay::pending($ssl); | 
| 1381 | 78 | 100 | 66 |  |  | 663 | if ( $pending and | 
| 1382 |  |  |  |  |  |  | ( my $pb = Net::SSLeay::peek( $ssl,$pending )) ne '' ) { | 
| 1383 | 58 |  |  |  |  | 176 | $buf .= $pb | 
| 1384 |  |  |  |  |  |  | } else { | 
| 1385 | 20 | 100 |  |  |  | 192 | return $buf eq '' ? ():$buf; | 
| 1386 |  |  |  |  |  |  | } | 
| 1387 | 58 | 50 |  |  |  | 168 | if ( !$eod ) { | 
| 1388 | 58 |  |  |  |  | 168 | my $pos = index( $buf,$delim0 ); | 
| 1389 | 58 | 100 |  |  |  | 156 | if ( $pos<0 ) { | 
| 1390 | 3 |  |  |  |  | 11 | $skip = $pending | 
| 1391 |  |  |  |  |  |  | } else { | 
| 1392 | 55 |  |  |  |  | 132 | $eod = $pos + length($delim0); # pos after delim0 | 
| 1393 |  |  |  |  |  |  | } | 
| 1394 |  |  |  |  |  |  | } | 
| 1395 |  |  |  |  |  |  |  | 
| 1396 | 58 | 100 |  |  |  | 155 | if ( $eod ) { | 
| 1397 | 55 | 100 |  |  |  | 298 | if ( $delim1 ne '' ) { | 
| 1398 |  |  |  |  |  |  | # delim0 found, check for as much delim1 as possible | 
| 1399 | 1 |  |  |  |  | 5 | while ( index( $buf,$delim1,$eod ) == $eod ) { | 
| 1400 | 2 |  |  |  |  | 5 | $eod+= length($delim1); | 
| 1401 |  |  |  |  |  |  | } | 
| 1402 |  |  |  |  |  |  | } | 
| 1403 | 55 |  |  |  |  | 134 | $skip = $pending - ( length($buf) - $eod ); | 
| 1404 |  |  |  |  |  |  | } | 
| 1405 |  |  |  |  |  |  |  | 
| 1406 |  |  |  |  |  |  | # remove data from $self which I already have in buf | 
| 1407 | 58 |  |  |  |  | 180 | while ( $skip>0 ) { | 
| 1408 | 58 | 50 |  |  |  | 333 | if ($self->sysread(my $p,$skip,0)) { | 
| 1409 | 58 |  |  |  |  | 119 | $skip -= length($p); | 
| 1410 | 58 |  |  |  |  | 196 | next; | 
| 1411 |  |  |  |  |  |  | } | 
| 1412 | 0 | 0 |  |  |  | 0 | $! == EINTR or last; | 
| 1413 |  |  |  |  |  |  | } | 
| 1414 |  |  |  |  |  |  |  | 
| 1415 | 58 | 50 | 66 |  |  | 413 | if ( $eod and ( $delim1 eq '' or $eod < length($buf))) { | 
|  |  |  | 100 |  |  |  |  | 
| 1416 |  |  |  |  |  |  | # delim0 found and there can be no more delim1 pending | 
| 1417 |  |  |  |  |  |  | last | 
| 1418 | 55 |  |  |  |  | 149 | } | 
| 1419 |  |  |  |  |  |  | } | 
| 1420 | 55 |  |  |  |  | 374 | return substr($buf,0,$eod); | 
| 1421 |  |  |  |  |  |  | } | 
| 1422 |  |  |  |  |  |  |  | 
| 1423 |  |  |  |  |  |  | sub close { | 
| 1424 | 248 |  | 50 | 248 | 1 | 3291 | my $self = shift || return _invalid_object(); | 
| 1425 | 248 | 50 |  |  |  | 2429 | my $close_args = (ref($_[0]) eq 'HASH') ? $_[0] : {@_}; | 
| 1426 |  |  |  |  |  |  |  | 
| 1427 | 248 | 50 |  |  |  | 2766 | return if ! $self->stop_SSL( | 
| 1428 |  |  |  |  |  |  | SSL_fast_shutdown => 1, | 
| 1429 |  |  |  |  |  |  | %$close_args, | 
| 1430 |  |  |  |  |  |  | _SSL_ioclass_downgrade => 0, | 
| 1431 |  |  |  |  |  |  | ); | 
| 1432 |  |  |  |  |  |  |  | 
| 1433 | 248 | 100 |  |  |  | 911 | if ( ! $close_args->{_SSL_in_DESTROY} ) { | 
| 1434 | 51 |  |  |  |  | 152 | untie( *$self ); | 
| 1435 | 51 |  |  |  |  | 85 | undef ${*$self}{_SSL_fileno}; | 
|  | 51 |  |  |  |  | 183 |  | 
| 1436 | 51 |  |  |  |  | 389 | return $self->SUPER::close; | 
| 1437 |  |  |  |  |  |  | } | 
| 1438 | 197 |  |  |  |  | 612 | return 1; | 
| 1439 |  |  |  |  |  |  | } | 
| 1440 |  |  |  |  |  |  |  | 
| 1441 |  |  |  |  |  |  | sub is_SSL { | 
| 1442 | 0 |  |  | 0 | 0 | 0 | my $self = pop; | 
| 1443 | 0 |  | 0 |  |  | 0 | return ${*$self}{_SSL_object} && 1 | 
| 1444 |  |  |  |  |  |  | } | 
| 1445 |  |  |  |  |  |  |  | 
| 1446 |  |  |  |  |  |  | sub stop_SSL { | 
| 1447 | 297 |  | 50 | 297 | 1 | 4730 | my $self = shift || return _invalid_object(); | 
| 1448 | 297 | 50 |  |  |  | 1795 | my $stop_args = (ref($_[0]) eq 'HASH') ? $_[0] : {@_}; | 
| 1449 | 297 | 100 |  |  |  | 662 | $stop_args->{SSL_no_shutdown} = 1 if ! ${*$self}{_SSL_opened}; | 
|  | 297 |  |  |  |  | 1416 |  | 
| 1450 |  |  |  |  |  |  |  | 
| 1451 | 297 | 100 |  |  |  | 697 | if (my $ssl = ${*$self}{'_SSL_object'}) { | 
|  | 297 |  |  |  |  | 1242 |  | 
| 1452 | 295 | 50 |  |  |  | 631 | if (delete ${*$self}{'_SSL_opening'}) { | 
|  | 295 | 100 |  |  |  | 1573 |  | 
| 1453 |  |  |  |  |  |  | # just destroy the object further below | 
| 1454 |  |  |  |  |  |  | } elsif ( ! $stop_args->{SSL_no_shutdown} ) { | 
| 1455 | 97 |  |  |  |  | 437 | my $status = Net::SSLeay::get_shutdown($ssl); | 
| 1456 |  |  |  |  |  |  |  | 
| 1457 |  |  |  |  |  |  | my $timeout = | 
| 1458 |  |  |  |  |  |  | not($self->blocking) ? undef : | 
| 1459 |  |  |  |  |  |  | exists $stop_args->{Timeout} ? $stop_args->{Timeout} : | 
| 1460 | 97 | 50 |  |  |  | 874 | ${*$self}{io_socket_timeout}; # from IO::Socket | 
|  | 85 | 100 |  |  |  | 2249 |  | 
| 1461 | 97 | 100 |  |  |  | 642 | if ($timeout) { | 
| 1462 | 3 |  |  |  |  | 10 | $self->blocking(0); | 
| 1463 | 3 |  |  |  |  | 38 | $timeout += time(); | 
| 1464 |  |  |  |  |  |  | } | 
| 1465 |  |  |  |  |  |  |  | 
| 1466 | 97 |  |  |  |  | 206 | while (1) { | 
| 1467 | 156 | 100 | 100 |  |  | 1050 | if ( $status & SSL_SENT_SHUTDOWN and | 
|  |  |  | 100 |  |  |  |  | 
| 1468 |  |  |  |  |  |  | # don't care for received if fast shutdown | 
| 1469 |  |  |  |  |  |  | $status & SSL_RECEIVED_SHUTDOWN | 
| 1470 |  |  |  |  |  |  | || $stop_args->{SSL_fast_shutdown}) { | 
| 1471 |  |  |  |  |  |  | # shutdown complete | 
| 1472 | 49 |  |  |  |  | 126 | last; | 
| 1473 |  |  |  |  |  |  | } | 
| 1474 | 107 | 100 | 50 |  |  | 210 | if ((${*$self}{'_SSL_opened'}||0) <= 0) { | 
| 1475 |  |  |  |  |  |  | # not really open, thus don't expect shutdown to return | 
| 1476 |  |  |  |  |  |  | # something meaningful | 
| 1477 | 48 |  |  |  |  | 125 | last; | 
| 1478 |  |  |  |  |  |  | } | 
| 1479 |  |  |  |  |  |  |  | 
| 1480 |  |  |  |  |  |  | # initiate or complete shutdown | 
| 1481 | 59 |  |  |  |  | 1467 | local $SIG{PIPE} = 'IGNORE'; | 
| 1482 | 59 |  |  |  |  | 249 | $SSL_ERROR = $! = undef; | 
| 1483 | 59 |  |  |  |  | 4067 | my $rv = Net::SSLeay::shutdown($ssl); | 
| 1484 | 59 | 50 |  |  |  | 343 | if ( $rv < 0 ) { | 
| 1485 |  |  |  |  |  |  | # non-blocking socket? | 
| 1486 | 0 | 0 |  |  |  | 0 | if ( ! $timeout ) { | 
| 1487 | 0 | 0 |  |  |  | 0 | if ( my $err = $self->_skip_rw_error( $ssl, $rv )) { | 
| 1488 |  |  |  |  |  |  | # if $! is not set with ERROR_SYSCALL then report as EPIPE | 
| 1489 | 0 | 0 | 0 |  |  | 0 | $! ||= EPIPE if $err == $Net_SSLeay_ERROR_SYSCALL; | 
| 1490 | 0 |  |  |  |  | 0 | $self->error("SSL shutdown error ($err)"); | 
| 1491 |  |  |  |  |  |  | } | 
| 1492 |  |  |  |  |  |  | # need to try again | 
| 1493 | 0 |  |  |  |  | 0 | return; | 
| 1494 |  |  |  |  |  |  | } | 
| 1495 |  |  |  |  |  |  |  | 
| 1496 |  |  |  |  |  |  | # don't use _skip_rw_error so that existing error does | 
| 1497 |  |  |  |  |  |  | # not get cleared | 
| 1498 | 0 |  |  |  |  | 0 | my $wait = $timeout - time(); | 
| 1499 | 0 | 0 |  |  |  | 0 | last if $wait<=0; | 
| 1500 | 0 |  |  |  |  | 0 | vec(my $vec = '',fileno($self),1) = 1; | 
| 1501 | 0 |  |  |  |  | 0 | my $err = Net::SSLeay::get_error($ssl,$rv); | 
| 1502 | 0 | 0 |  |  |  | 0 | if ( $err == $Net_SSLeay_ERROR_WANT_READ) { | 
|  |  | 0 |  |  |  |  |  | 
| 1503 | 0 |  |  |  |  | 0 | select($vec,undef,undef,$wait) | 
| 1504 |  |  |  |  |  |  | } elsif ( $err == $Net_SSLeay_ERROR_WANT_READ) { | 
| 1505 | 0 |  |  |  |  | 0 | select(undef,$vec,undef,$wait) | 
| 1506 |  |  |  |  |  |  | } else { | 
| 1507 | 0 |  |  |  |  | 0 | last; | 
| 1508 |  |  |  |  |  |  | } | 
| 1509 |  |  |  |  |  |  | } | 
| 1510 |  |  |  |  |  |  |  | 
| 1511 | 59 |  |  |  |  | 153 | $status |= SSL_SENT_SHUTDOWN; | 
| 1512 | 59 | 100 |  |  |  | 1009 | $status |= SSL_RECEIVED_SHUTDOWN if $rv>0; | 
| 1513 |  |  |  |  |  |  | } | 
| 1514 | 97 | 100 |  |  |  | 375 | $self->blocking(1) if $timeout; | 
| 1515 |  |  |  |  |  |  | } | 
| 1516 |  |  |  |  |  |  |  | 
| 1517 |  |  |  |  |  |  | # destroy allocated objects for SSL and untie | 
| 1518 |  |  |  |  |  |  | # do not destroy CTX unless explicitly specified | 
| 1519 | 295 |  |  |  |  | 10405 | Net::SSLeay::free($ssl); | 
| 1520 | 295 | 100 |  |  |  | 724 | if (my $cert = delete ${*$self}{'_SSL_certificate'}) { | 
|  | 295 |  |  |  |  | 1650 |  | 
| 1521 | 37 |  |  |  |  | 713 | Net::SSLeay::X509_free($cert); | 
| 1522 |  |  |  |  |  |  | } | 
| 1523 | 295 |  |  |  |  | 10661 | delete ${*$self}{_SSL_object}; | 
|  | 295 |  |  |  |  | 884 |  | 
| 1524 | 295 |  |  |  |  | 653 | ${*$self}{'_SSL_opened'} = 0; | 
|  | 295 |  |  |  |  | 789 |  | 
| 1525 | 295 |  |  |  |  | 12052 | delete $SSL_OBJECT{$ssl}; | 
| 1526 | 295 |  |  |  |  | 578 | delete $CREATED_IN_THIS_THREAD{$ssl}; | 
| 1527 | 295 |  |  |  |  | 3629 | untie(*$self); | 
| 1528 |  |  |  |  |  |  | } | 
| 1529 |  |  |  |  |  |  |  | 
| 1530 | 297 | 100 |  |  |  | 10217 | if ($stop_args->{'SSL_ctx_free'}) { | 
| 1531 | 3 |  |  |  |  | 6 | my $ctx = delete ${*$self}{'_SSL_ctx'}; | 
|  | 3 |  |  |  |  | 9 |  | 
| 1532 | 3 | 50 |  |  |  | 60 | $ctx && $ctx->DESTROY(); | 
| 1533 |  |  |  |  |  |  | } | 
| 1534 |  |  |  |  |  |  |  | 
| 1535 |  |  |  |  |  |  |  | 
| 1536 | 297 | 100 |  |  |  | 1091 | if ( ! $stop_args->{_SSL_in_DESTROY} ) { | 
| 1537 |  |  |  |  |  |  |  | 
| 1538 | 100 |  |  |  |  | 212 | my $downgrade = $stop_args->{_SSL_ioclass_downgrade}; | 
| 1539 | 100 | 100 | 66 |  |  | 830 | if ( $downgrade || ! defined $downgrade ) { | 
| 1540 |  |  |  |  |  |  | # rebless to original class from start_SSL | 
| 1541 | 49 | 100 |  |  |  | 100 | if ( my $orig_class = delete ${*$self}{'_SSL_ioclass_upgraded'} ) { | 
|  | 49 |  |  |  |  | 234 |  | 
| 1542 | 42 |  |  |  |  | 258 | bless $self,$orig_class; | 
| 1543 |  |  |  |  |  |  | # FIXME: if original class was tied too we need to restore the tie | 
| 1544 |  |  |  |  |  |  | # remove all _SSL related from *$self | 
| 1545 | 42 |  |  |  |  | 87 | my @sslkeys = grep { m{^_?SSL_} } keys %{*$self}; | 
|  | 399 |  |  |  |  | 1901 |  | 
|  | 42 |  |  |  |  | 308 |  | 
| 1546 | 42 | 50 |  |  |  | 195 | delete @{*$self}{@sslkeys} if @sslkeys; | 
|  | 42 |  |  |  |  | 292 |  | 
| 1547 |  |  |  |  |  |  | } | 
| 1548 |  |  |  |  |  |  | } | 
| 1549 |  |  |  |  |  |  | } | 
| 1550 | 297 |  |  |  |  | 1465 | return 1; | 
| 1551 |  |  |  |  |  |  | } | 
| 1552 |  |  |  |  |  |  |  | 
| 1553 |  |  |  |  |  |  |  | 
| 1554 |  |  |  |  |  |  | sub fileno { | 
| 1555 | 7345 |  |  | 7345 | 0 | 78824 | my $self = shift; | 
| 1556 | 7345 |  |  |  |  | 10210 | my $fn = ${*$self}{'_SSL_fileno'}; | 
|  | 7345 |  |  |  |  | 19032 |  | 
| 1557 | 7345 | 100 |  |  |  | 22980 | return defined($fn) ? $fn : $self->SUPER::fileno(); | 
| 1558 |  |  |  |  |  |  | } | 
| 1559 |  |  |  |  |  |  |  | 
| 1560 |  |  |  |  |  |  |  | 
| 1561 |  |  |  |  |  |  | ####### IO::Socket::SSL specific functions ####### | 
| 1562 |  |  |  |  |  |  | # _get_ssl_object is for internal use ONLY! | 
| 1563 |  |  |  |  |  |  | sub _get_ssl_object { | 
| 1564 | 245 |  |  | 245 |  | 4982 | my $self = shift; | 
| 1565 | 245 |  | 33 |  |  | 410 | return ${*$self}{'_SSL_object'} || | 
| 1566 |  |  |  |  |  |  | IO::Socket::SSL->_internal_error("Undefined SSL object",9); | 
| 1567 |  |  |  |  |  |  | } | 
| 1568 |  |  |  |  |  |  |  | 
| 1569 |  |  |  |  |  |  | # _get_ctx_object is for internal use ONLY! | 
| 1570 |  |  |  |  |  |  | sub _get_ctx_object { | 
| 1571 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 1572 | 0 |  |  |  |  | 0 | my $ctx_object = ${*$self}{_SSL_ctx}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1573 | 0 |  | 0 |  |  | 0 | return $ctx_object && $ctx_object->{context}; | 
| 1574 |  |  |  |  |  |  | } | 
| 1575 |  |  |  |  |  |  |  | 
| 1576 |  |  |  |  |  |  | # default error for undefined arguments | 
| 1577 |  |  |  |  |  |  | sub _invalid_object { | 
| 1578 | 0 |  |  | 0 |  | 0 | return IO::Socket::SSL->_internal_error("Undefined IO::Socket::SSL object",9); | 
| 1579 |  |  |  |  |  |  | } | 
| 1580 |  |  |  |  |  |  |  | 
| 1581 |  |  |  |  |  |  |  | 
| 1582 |  |  |  |  |  |  | sub pending { | 
| 1583 | 1 |  | 50 | 1 | 1 | 5 | my $ssl = shift()->_get_ssl_object || return; | 
| 1584 | 1 |  |  |  |  | 8 | return Net::SSLeay::pending($ssl); | 
| 1585 |  |  |  |  |  |  | } | 
| 1586 |  |  |  |  |  |  |  | 
| 1587 |  |  |  |  |  |  | sub start_SSL { | 
| 1588 | 162 |  |  | 162 | 1 | 15092710 | my ($class,$socket) = (shift,shift); | 
| 1589 | 162 | 50 |  |  |  | 1983 | return $class->_internal_error("Not a socket",9) if ! ref($socket); | 
| 1590 | 162 | 100 |  |  |  | 3147 | my $arg_hash = @_ == 1 ? $_[0] : {@_}; | 
| 1591 | 162 | 100 |  |  |  | 2119 | my %to = exists $arg_hash->{Timeout} ? ( Timeout => delete $arg_hash->{Timeout} ) :(); | 
| 1592 | 162 |  |  |  |  | 644 | my $original_class = ref($socket); | 
| 1593 | 162 | 50 |  |  |  | 1135 | if ( ! $original_class ) { | 
| 1594 | 0 | 0 |  |  |  | 0 | $socket = ($original_class = $ISA[0])->new_from_fd($socket,'<+') | 
| 1595 |  |  |  |  |  |  | or return $class->_internal_error( | 
| 1596 |  |  |  |  |  |  | "creating $original_class from file handle failed",9); | 
| 1597 |  |  |  |  |  |  | } | 
| 1598 | 162 | 50 |  |  |  | 3287 | my $original_fileno = (UNIVERSAL::can($socket, "fileno")) | 
| 1599 |  |  |  |  |  |  | ? $socket->fileno : CORE::fileno($socket); | 
| 1600 | 162 | 100 |  |  |  | 2456 | return $class->_internal_error("Socket has no fileno",9) | 
| 1601 |  |  |  |  |  |  | if ! defined $original_fileno; | 
| 1602 |  |  |  |  |  |  |  | 
| 1603 | 161 |  |  |  |  | 807 | bless $socket, $class; | 
| 1604 | 161 | 50 | 0 |  |  | 2250 | $socket->configure_SSL($arg_hash) or bless($socket, $original_class) && return; | 
| 1605 |  |  |  |  |  |  |  | 
| 1606 | 161 |  |  |  |  | 377 | ${*$socket}{'_SSL_fileno'} = $original_fileno; | 
|  | 161 |  |  |  |  | 1112 |  | 
| 1607 | 161 | 100 |  |  |  | 708 | ${*$socket}{'_SSL_ioclass_upgraded'} = $original_class | 
|  | 160 |  |  |  |  | 943 |  | 
| 1608 |  |  |  |  |  |  | if $class ne $original_class; | 
| 1609 |  |  |  |  |  |  |  | 
| 1610 | 161 |  |  |  |  | 509 | my $start_handshake = $arg_hash->{SSL_startHandshake}; | 
| 1611 | 161 | 100 | 66 |  |  | 725 | if ( ! defined($start_handshake) || $start_handshake ) { | 
| 1612 |  |  |  |  |  |  | # if we have no callback force blocking mode | 
| 1613 | 157 | 50 |  |  |  | 495 | $DEBUG>=2 && DEBUG( "start handshake" ); | 
| 1614 | 157 |  |  |  |  | 1616 | my $was_blocking = $socket->blocking(1); | 
| 1615 | 157 |  |  |  |  | 2141 | my $result = ${*$socket}{'_SSL_arguments'}{SSL_server} | 
| 1616 | 157 | 100 |  |  |  | 3944 | ? $socket->accept_SSL(%to) | 
| 1617 |  |  |  |  |  |  | : $socket->connect_SSL(%to); | 
| 1618 | 157 | 100 |  |  |  | 665 | if ( $result ) { | 
| 1619 | 116 | 50 |  |  |  | 373 | $socket->blocking(0) if ! $was_blocking; | 
| 1620 | 116 |  |  |  |  | 936 | return $socket; | 
| 1621 |  |  |  |  |  |  | } else { | 
| 1622 |  |  |  |  |  |  | # upgrade to SSL failed, downgrade socket to original class | 
| 1623 | 41 | 50 |  |  |  | 141 | if ( $original_class ) { | 
| 1624 | 41 |  |  |  |  | 127 | bless($socket,$original_class); | 
| 1625 | 41 | 50 | 33 |  |  | 184 | $socket->blocking(0) if ! $was_blocking | 
| 1626 |  |  |  |  |  |  | && $socket->can('blocking'); | 
| 1627 |  |  |  |  |  |  | } | 
| 1628 | 41 |  |  |  |  | 695 | return; | 
| 1629 |  |  |  |  |  |  | } | 
| 1630 |  |  |  |  |  |  | } else { | 
| 1631 | 4 | 50 |  |  |  | 14 | $DEBUG>=2 && DEBUG( "don't start handshake: $socket" ); | 
| 1632 | 4 |  |  |  |  | 19 | return $socket; # just return upgraded socket | 
| 1633 |  |  |  |  |  |  | } | 
| 1634 |  |  |  |  |  |  |  | 
| 1635 |  |  |  |  |  |  | } | 
| 1636 |  |  |  |  |  |  |  | 
| 1637 |  |  |  |  |  |  | sub new_from_fd { | 
| 1638 | 1 |  |  | 1 | 1 | 902 | my ($class, $fd) = (shift,shift); | 
| 1639 |  |  |  |  |  |  | # Check for accidental inclusion of MODE in the argument list | 
| 1640 | 1 | 50 |  |  |  | 6 | if (length($_[0]) < 4) { | 
| 1641 | 1 |  |  |  |  | 8 | (my $mode = $_[0]) =~ tr/+<>//d; | 
| 1642 | 1 | 50 |  |  |  | 5 | shift unless length($mode); | 
| 1643 |  |  |  |  |  |  | } | 
| 1644 | 1 |  | 50 |  |  | 46 | my $handle = $ISA[0]->new_from_fd($fd, '+<') | 
| 1645 |  |  |  |  |  |  | || return($class->error("Could not create socket from file descriptor.")); | 
| 1646 |  |  |  |  |  |  |  | 
| 1647 |  |  |  |  |  |  | # Annoying workaround for Perl 5.6.1 and below: | 
| 1648 | 1 |  |  |  |  | 158 | $handle = $ISA[0]->new_from_fd($handle, '+<'); | 
| 1649 |  |  |  |  |  |  |  | 
| 1650 | 1 |  |  |  |  | 141 | return $class->start_SSL($handle, @_); | 
| 1651 |  |  |  |  |  |  | } | 
| 1652 |  |  |  |  |  |  |  | 
| 1653 |  |  |  |  |  |  |  | 
| 1654 |  |  |  |  |  |  | sub dump_peer_certificate { | 
| 1655 | 1 |  | 50 | 1 | 1 | 6 | my $ssl = shift()->_get_ssl_object || return; | 
| 1656 | 1 |  |  |  |  | 8 | return Net::SSLeay::dump_peer_certificate($ssl); | 
| 1657 |  |  |  |  |  |  | } | 
| 1658 |  |  |  |  |  |  |  | 
| 1659 |  |  |  |  |  |  | if ( defined &Net::SSLeay::get_peer_cert_chain | 
| 1660 |  |  |  |  |  |  | && $netssleay_version >= 1.58 ) { | 
| 1661 |  |  |  |  |  |  | *peer_certificates = sub { | 
| 1662 | 6 |  |  | 6 |  | 26 | my $self = shift; | 
| 1663 | 6 |  | 50 |  |  | 33 | my $ssl = $self->_get_ssl_object || return; | 
| 1664 | 6 |  |  |  |  | 36 | my @chain = Net::SSLeay::get_peer_cert_chain($ssl); | 
| 1665 | 6 | 50 | 33 |  |  | 31 | @chain = () if @chain && !$self->peer_certificate; # work around #96013 | 
| 1666 | 6 | 50 |  |  |  | 11 | if ( ${*$self}{_SSL_arguments}{SSL_server} ) { | 
|  | 6 |  |  |  |  | 27 |  | 
| 1667 |  |  |  |  |  |  | # in the client case the chain contains the peer certificate, | 
| 1668 |  |  |  |  |  |  | # in the server case not | 
| 1669 |  |  |  |  |  |  | # this one has an increased reference counter, the other not | 
| 1670 | 0 | 0 |  |  |  | 0 | if ( my $peer = Net::SSLeay::get_peer_certificate($ssl)) { | 
| 1671 | 0 |  |  |  |  | 0 | Net::SSLeay::X509_free($peer); | 
| 1672 | 0 |  |  |  |  | 0 | unshift @chain, $peer; | 
| 1673 |  |  |  |  |  |  | } | 
| 1674 |  |  |  |  |  |  | } | 
| 1675 | 6 |  |  |  |  | 43 | return @chain; | 
| 1676 |  |  |  |  |  |  |  | 
| 1677 |  |  |  |  |  |  | } | 
| 1678 |  |  |  |  |  |  | } else { | 
| 1679 |  |  |  |  |  |  | *peer_certificates = sub { | 
| 1680 |  |  |  |  |  |  | die "peer_certificates needs Net::SSLeay>=1.58"; | 
| 1681 |  |  |  |  |  |  | } | 
| 1682 |  |  |  |  |  |  | } | 
| 1683 |  |  |  |  |  |  |  | 
| 1684 |  |  |  |  |  |  | { | 
| 1685 |  |  |  |  |  |  | my %dispatcher = ( | 
| 1686 |  |  |  |  |  |  | issuer =>  sub { Net::SSLeay::X509_NAME_oneline( Net::SSLeay::X509_get_issuer_name( shift )) }, | 
| 1687 |  |  |  |  |  |  | subject => sub { Net::SSLeay::X509_NAME_oneline( Net::SSLeay::X509_get_subject_name( shift )) }, | 
| 1688 |  |  |  |  |  |  | commonName => sub { | 
| 1689 |  |  |  |  |  |  | my $cn = Net::SSLeay::X509_NAME_get_text_by_NID( | 
| 1690 |  |  |  |  |  |  | Net::SSLeay::X509_get_subject_name( shift ), NID_CommonName); | 
| 1691 |  |  |  |  |  |  | $cn; | 
| 1692 |  |  |  |  |  |  | }, | 
| 1693 |  |  |  |  |  |  | subjectAltNames => sub { Net::SSLeay::X509_get_subjectAltNames( shift ) }, | 
| 1694 |  |  |  |  |  |  | ); | 
| 1695 |  |  |  |  |  |  |  | 
| 1696 |  |  |  |  |  |  | # alternative names | 
| 1697 |  |  |  |  |  |  | $dispatcher{authority} = $dispatcher{issuer}; | 
| 1698 |  |  |  |  |  |  | $dispatcher{owner}     = $dispatcher{subject}; | 
| 1699 |  |  |  |  |  |  | $dispatcher{cn}        = $dispatcher{commonName}; | 
| 1700 |  |  |  |  |  |  |  | 
| 1701 |  |  |  |  |  |  | sub peer_certificate { | 
| 1702 | 85 |  |  | 85 | 1 | 2240 | my ($self,$field,$reload) = @_; | 
| 1703 | 85 | 50 |  |  |  | 258 | my $ssl = $self->_get_ssl_object or return; | 
| 1704 |  |  |  |  |  |  |  | 
| 1705 | 0 |  |  |  |  | 0 | Net::SSLeay::X509_free(delete ${*$self}{_SSL_certificate}) | 
| 1706 | 85 | 0 | 33 |  |  | 286 | if $reload && ${*$self}{_SSL_certificate}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1707 | 85 |  |  |  |  | 679 | my $cert = ${*$self}{_SSL_certificate} | 
| 1708 | 85 | 50 | 66 |  |  | 136 | ||= Net::SSLeay::get_peer_certificate($ssl) | 
| 1709 |  |  |  |  |  |  | or return $self->error("Could not retrieve peer certificate"); | 
| 1710 |  |  |  |  |  |  |  | 
| 1711 | 85 | 100 |  |  |  | 9859 | if ($field) { | 
| 1712 | 14 | 50 |  |  |  | 66 | my $sub = $dispatcher{$field} or croak | 
| 1713 |  |  |  |  |  |  | "invalid argument for peer_certificate, valid are: ".join( " ",keys %dispatcher ). | 
| 1714 |  |  |  |  |  |  | "\nMaybe you need to upgrade your Net::SSLeay"; | 
| 1715 | 14 |  |  |  |  | 71 | return $sub->($cert); | 
| 1716 |  |  |  |  |  |  | } else { | 
| 1717 | 71 |  |  |  |  | 224 | return $cert | 
| 1718 |  |  |  |  |  |  | } | 
| 1719 |  |  |  |  |  |  | } | 
| 1720 |  |  |  |  |  |  |  | 
| 1721 |  |  |  |  |  |  | sub sock_certificate { | 
| 1722 | 6 |  |  | 6 | 1 | 828 | my ($self,$field) = @_; | 
| 1723 | 6 |  | 50 |  |  | 29 | my $ssl = $self->_get_ssl_object || return; | 
| 1724 | 6 |  | 50 |  |  | 24 | my $cert = Net::SSLeay::get_certificate( $ssl ) || return; | 
| 1725 | 6 | 100 |  |  |  | 16 | if ($field) { | 
| 1726 | 4 | 50 |  |  |  | 30 | my $sub = $dispatcher{$field} or croak | 
| 1727 |  |  |  |  |  |  | "invalid argument for sock_certificate, valid are: ".join( " ",keys %dispatcher ). | 
| 1728 |  |  |  |  |  |  | "\nMaybe you need to upgrade your Net::SSLeay"; | 
| 1729 | 4 |  |  |  |  | 20 | return $sub->($cert); | 
| 1730 |  |  |  |  |  |  | } else { | 
| 1731 | 2 |  |  |  |  | 43 | return $cert | 
| 1732 |  |  |  |  |  |  | } | 
| 1733 |  |  |  |  |  |  | } | 
| 1734 |  |  |  |  |  |  |  | 
| 1735 |  |  |  |  |  |  |  | 
| 1736 |  |  |  |  |  |  | # known schemes, possible attributes are: | 
| 1737 |  |  |  |  |  |  | #  - wildcards_in_alt (0, 'full_label', 'anywhere') | 
| 1738 |  |  |  |  |  |  | #  - wildcards_in_cn (0, 'full_label', 'anywhere') | 
| 1739 |  |  |  |  |  |  | #  - check_cn (0, 'always', 'when_only') | 
| 1740 |  |  |  |  |  |  | # unfortunately there are a lot of different schemes used, see RFC 6125 for a | 
| 1741 |  |  |  |  |  |  | # summary, which references all of the following except RFC4217/ftp | 
| 1742 |  |  |  |  |  |  |  | 
| 1743 |  |  |  |  |  |  | my %scheme = ( | 
| 1744 |  |  |  |  |  |  | none => {}, # do not check | 
| 1745 |  |  |  |  |  |  | # default set is a superset of all the others and thus worse than a more | 
| 1746 |  |  |  |  |  |  | # specific set, but much better than not verifying name at all | 
| 1747 |  |  |  |  |  |  | default => { | 
| 1748 |  |  |  |  |  |  | wildcards_in_cn  => 'anywhere', | 
| 1749 |  |  |  |  |  |  | wildcards_in_alt => 'anywhere', | 
| 1750 |  |  |  |  |  |  | check_cn         => 'always', | 
| 1751 |  |  |  |  |  |  | ip_in_cn         => 1, | 
| 1752 |  |  |  |  |  |  | }, | 
| 1753 |  |  |  |  |  |  | ); | 
| 1754 |  |  |  |  |  |  |  | 
| 1755 |  |  |  |  |  |  | for(qw( | 
| 1756 |  |  |  |  |  |  | rfc2818 | 
| 1757 |  |  |  |  |  |  | rfc3920 xmpp | 
| 1758 |  |  |  |  |  |  | rfc4217 ftp | 
| 1759 |  |  |  |  |  |  | )) { | 
| 1760 |  |  |  |  |  |  | $scheme{$_} = { | 
| 1761 |  |  |  |  |  |  | wildcards_in_cn  => 'anywhere', | 
| 1762 |  |  |  |  |  |  | wildcards_in_alt => 'anywhere', | 
| 1763 |  |  |  |  |  |  | check_cn         => 'when_only', | 
| 1764 |  |  |  |  |  |  | } | 
| 1765 |  |  |  |  |  |  | } | 
| 1766 |  |  |  |  |  |  |  | 
| 1767 |  |  |  |  |  |  | for(qw(www http)) { | 
| 1768 |  |  |  |  |  |  | $scheme{$_} = { | 
| 1769 |  |  |  |  |  |  | wildcards_in_cn  => 'anywhere', | 
| 1770 |  |  |  |  |  |  | wildcards_in_alt => 'anywhere', | 
| 1771 |  |  |  |  |  |  | check_cn         => 'when_only', | 
| 1772 |  |  |  |  |  |  | ip_in_cn         => 4, | 
| 1773 |  |  |  |  |  |  | } | 
| 1774 |  |  |  |  |  |  | } | 
| 1775 |  |  |  |  |  |  |  | 
| 1776 |  |  |  |  |  |  | for(qw( | 
| 1777 |  |  |  |  |  |  | rfc4513 ldap | 
| 1778 |  |  |  |  |  |  | )) { | 
| 1779 |  |  |  |  |  |  | $scheme{$_} = { | 
| 1780 |  |  |  |  |  |  | wildcards_in_cn  => 0, | 
| 1781 |  |  |  |  |  |  | wildcards_in_alt => 'full_label', | 
| 1782 |  |  |  |  |  |  | check_cn         => 'always', | 
| 1783 |  |  |  |  |  |  | }; | 
| 1784 |  |  |  |  |  |  | } | 
| 1785 |  |  |  |  |  |  |  | 
| 1786 |  |  |  |  |  |  | for(qw( | 
| 1787 |  |  |  |  |  |  | rfc2595 smtp | 
| 1788 |  |  |  |  |  |  | rfc4642 imap pop3 acap | 
| 1789 |  |  |  |  |  |  | rfc5539 nntp | 
| 1790 |  |  |  |  |  |  | rfc5538 netconf | 
| 1791 |  |  |  |  |  |  | rfc5425 syslog | 
| 1792 |  |  |  |  |  |  | rfc5953 snmp | 
| 1793 |  |  |  |  |  |  | )) { | 
| 1794 |  |  |  |  |  |  | $scheme{$_} = { | 
| 1795 |  |  |  |  |  |  | wildcards_in_cn  => 'full_label', | 
| 1796 |  |  |  |  |  |  | wildcards_in_alt => 'full_label', | 
| 1797 |  |  |  |  |  |  | check_cn         => 'always' | 
| 1798 |  |  |  |  |  |  | }; | 
| 1799 |  |  |  |  |  |  | } | 
| 1800 |  |  |  |  |  |  | for(qw( | 
| 1801 |  |  |  |  |  |  | rfc5971 gist | 
| 1802 |  |  |  |  |  |  | )) { | 
| 1803 |  |  |  |  |  |  | $scheme{$_} = { | 
| 1804 |  |  |  |  |  |  | wildcards_in_cn  => 'full_label', | 
| 1805 |  |  |  |  |  |  | wildcards_in_alt => 'full_label', | 
| 1806 |  |  |  |  |  |  | check_cn         => 'when_only', | 
| 1807 |  |  |  |  |  |  | }; | 
| 1808 |  |  |  |  |  |  | } | 
| 1809 |  |  |  |  |  |  |  | 
| 1810 |  |  |  |  |  |  | for(qw( | 
| 1811 |  |  |  |  |  |  | rfc5922 sip | 
| 1812 |  |  |  |  |  |  | )) { | 
| 1813 |  |  |  |  |  |  | $scheme{$_} = { | 
| 1814 |  |  |  |  |  |  | wildcards_in_cn  => 0, | 
| 1815 |  |  |  |  |  |  | wildcards_in_alt => 0, | 
| 1816 |  |  |  |  |  |  | check_cn         => 'always', | 
| 1817 |  |  |  |  |  |  | }; | 
| 1818 |  |  |  |  |  |  | } | 
| 1819 |  |  |  |  |  |  |  | 
| 1820 |  |  |  |  |  |  |  | 
| 1821 |  |  |  |  |  |  | # function to verify the hostname | 
| 1822 |  |  |  |  |  |  | # | 
| 1823 |  |  |  |  |  |  | # as every application protocol has its own rules to do this | 
| 1824 |  |  |  |  |  |  | # we provide some default rules as well as a user-defined | 
| 1825 |  |  |  |  |  |  | # callback | 
| 1826 |  |  |  |  |  |  |  | 
| 1827 |  |  |  |  |  |  | sub verify_hostname_of_cert { | 
| 1828 | 209 |  |  | 209 | 0 | 859 | my $identity = shift; | 
| 1829 | 209 |  |  |  |  | 360 | my $cert = shift; | 
| 1830 | 209 |  | 100 |  |  | 733 | my $scheme = shift || 'default'; | 
| 1831 | 209 |  |  |  |  | 388 | my $publicsuffix = shift; | 
| 1832 | 209 | 50 |  |  |  | 596 | if ( ! ref($scheme) ) { | 
| 1833 | 209 | 50 |  |  |  | 536 | $DEBUG>=3 && DEBUG( "scheme=$scheme cert=$cert" ); | 
| 1834 | 209 |  | 33 |  |  | 904 | $scheme = $scheme{$scheme} || croak("scheme $scheme not defined"); | 
| 1835 |  |  |  |  |  |  | } | 
| 1836 |  |  |  |  |  |  |  | 
| 1837 | 209 | 50 |  |  |  | 595 | return 1 if ! %$scheme; # 'none' | 
| 1838 | 209 |  |  |  |  | 1264 | $identity =~s{\.+$}{}; # ignore absolutism | 
| 1839 |  |  |  |  |  |  |  | 
| 1840 |  |  |  |  |  |  | # get data from certificate | 
| 1841 | 209 |  |  |  |  | 719 | my $commonName = $dispatcher{cn}->($cert); | 
| 1842 | 209 |  |  |  |  | 555 | my @altNames = $dispatcher{subjectAltNames}->($cert); | 
| 1843 | 209 | 50 |  |  |  | 664 | $DEBUG>=3 && DEBUG("identity=$identity cn=$commonName alt=@altNames" ); | 
| 1844 |  |  |  |  |  |  |  | 
| 1845 | 209 | 50 |  |  |  | 555 | if ( my $sub = $scheme->{callback} ) { | 
| 1846 |  |  |  |  |  |  | # use custom callback | 
| 1847 | 0 |  |  |  |  | 0 | return $sub->($identity,$commonName,@altNames); | 
| 1848 |  |  |  |  |  |  | } | 
| 1849 |  |  |  |  |  |  |  | 
| 1850 |  |  |  |  |  |  | # is the given hostname an IP address? Then we have to convert to network byte order [RFC791][RFC2460] | 
| 1851 |  |  |  |  |  |  |  | 
| 1852 | 209 |  |  |  |  | 353 | my $ipn; | 
| 1853 | 209 | 100 |  |  |  | 1417 | if ( CAN_IPV6 and $identity =~m{:} ) { | 
|  |  | 100 |  |  |  |  |  | 
| 1854 |  |  |  |  |  |  | # no IPv4 or hostname have ':'  in it, try IPv6. | 
| 1855 | 12 | 100 |  |  |  | 53 | $identity =~m{[^\da-fA-F:\.]} and return; # invalid characters in name | 
| 1856 | 9 | 50 |  |  |  | 50 | $ipn = inet_pton(AF_INET6,$identity) or return; # invalid name | 
| 1857 |  |  |  |  |  |  | } elsif ( my @ip = $identity =~m{^(\d+)(?:\.(\d+)\.(\d+)\.(\d+)|[\d\.]*)$} ) { | 
| 1858 |  |  |  |  |  |  | # check for invalid IP/hostname | 
| 1859 | 49 | 100 | 66 |  |  | 265 | return if 4 != @ip or 4 != grep { defined($_) && $_<256 } @ip; | 
|  | 196 | 100 |  |  |  | 1018 |  | 
| 1860 | 46 |  |  |  |  | 294 | $ipn = pack("CCCC",@ip); | 
| 1861 |  |  |  |  |  |  | } else { | 
| 1862 |  |  |  |  |  |  | # assume hostname, check for umlauts etc | 
| 1863 | 148 | 100 |  |  |  | 500 | if ( $identity =~m{[^a-zA-Z0-9_.\-]} ) { | 
| 1864 | 5 | 50 |  |  |  | 17 | $identity =~m{\0} and return; # $identity has \\0 byte | 
| 1865 | 5 | 50 |  |  |  | 28 | $identity = idn_to_ascii($identity) | 
| 1866 |  |  |  |  |  |  | or return; # conversation to IDNA failed | 
| 1867 | 5 | 100 |  |  |  | 733 | $identity =~m{[^a-zA-Z0-9_.\-]} | 
| 1868 |  |  |  |  |  |  | and return; # still junk inside | 
| 1869 |  |  |  |  |  |  | } | 
| 1870 |  |  |  |  |  |  | } | 
| 1871 |  |  |  |  |  |  |  | 
| 1872 |  |  |  |  |  |  | # do the actual verification | 
| 1873 |  |  |  |  |  |  | my $check_name = sub { | 
| 1874 | 313 |  |  | 313 |  | 771 | my ($name,$identity,$wtyp,$publicsuffix) = @_; | 
| 1875 | 313 |  |  |  |  | 846 | $name =~s{\.+$}{}; # ignore absolutism | 
| 1876 | 313 | 100 |  |  |  | 706 | $name eq '' and return; | 
| 1877 | 312 |  | 100 |  |  | 709 | $wtyp ||= ''; | 
| 1878 | 312 |  |  |  |  | 419 | my $pattern; | 
| 1879 |  |  |  |  |  |  | ### IMPORTANT! | 
| 1880 |  |  |  |  |  |  | # We accept only a single wildcard and only for a single part of the FQDN | 
| 1881 |  |  |  |  |  |  | # e.g. *.example.org does match www.example.org but not bla.www.example.org | 
| 1882 |  |  |  |  |  |  | # The RFCs are in this regard unspecific but we don't want to have to | 
| 1883 |  |  |  |  |  |  | # deal with certificates like *.com, *.co.uk or even * | 
| 1884 |  |  |  |  |  |  | # see also http://nils.toedtmann.net/pub/subjectAltName.txt . | 
| 1885 |  |  |  |  |  |  | # Also, we fall back to full_label matches if the identity is an IDNA | 
| 1886 |  |  |  |  |  |  | # name, see RFC6125 and the discussion at | 
| 1887 |  |  |  |  |  |  | # http://bugs.python.org/issue17997#msg194950 | 
| 1888 | 312 | 100 | 100 |  |  | 1941 | if ( $wtyp eq 'anywhere' and $name =~m{^([a-zA-Z0-9_\-]*)\*(.+)} ) { | 
|  |  | 100 | 100 |  |  |  |  | 
| 1889 | 116 | 100 | 100 |  |  | 622 | return if $1 ne '' and substr($identity,0,4) eq 'xn--'; # IDNA | 
| 1890 | 112 |  |  |  |  | 4122 | $pattern = qr{^\Q$1\E[a-zA-Z0-9_\-]+\Q$2\E$}i; | 
| 1891 |  |  |  |  |  |  | } elsif ( $wtyp =~ m{^(?:full_label|leftmost)$} | 
| 1892 |  |  |  |  |  |  | and $name =~m{^\*(\..+)$} ) { | 
| 1893 | 26 |  |  |  |  | 283 | $pattern = qr{^[a-zA-Z0-9_\-]+\Q$1\E$}i; | 
| 1894 |  |  |  |  |  |  | } else { | 
| 1895 | 170 |  |  |  |  | 1300 | return lc($identity) eq lc($name); | 
| 1896 |  |  |  |  |  |  | } | 
| 1897 | 138 | 100 |  |  |  | 1183 | if ( $identity =~ $pattern ) { | 
| 1898 | 56 | 50 |  |  |  | 742 | $publicsuffix = IO::Socket::SSL::PublicSuffix->default | 
| 1899 |  |  |  |  |  |  | if ! defined $publicsuffix; | 
| 1900 | 56 | 50 |  |  |  | 340 | return 1 if $publicsuffix eq ''; | 
| 1901 | 56 |  |  |  |  | 352 | my @labels = split( m{\.+}, $identity ); | 
| 1902 | 56 |  |  |  |  | 251 | my $tld = $publicsuffix->public_suffix(\@labels,+1); | 
| 1903 | 56 | 50 |  |  |  | 838 | return 1 if @labels > ( $tld ? 0+@$tld : 1 ); | 
|  |  | 100 |  |  |  |  |  | 
| 1904 |  |  |  |  |  |  | } | 
| 1905 | 97 |  |  |  |  | 449 | return; | 
| 1906 | 201 |  |  |  |  | 2278 | }; | 
| 1907 |  |  |  |  |  |  |  | 
| 1908 |  |  |  |  |  |  |  | 
| 1909 | 201 |  |  |  |  | 524 | my $alt_dnsNames = 0; | 
| 1910 | 201 |  |  |  |  | 615 | while (@altNames) { | 
| 1911 | 394 |  |  |  |  | 1041 | my ($type, $name) = splice (@altNames, 0, 2); | 
| 1912 | 394 | 100 | 100 |  |  | 1534 | if ( $ipn and $type == GEN_IPADD ) { | 
|  |  | 100 | 100 |  |  |  |  | 
| 1913 |  |  |  |  |  |  | # exact match needed for IP | 
| 1914 |  |  |  |  |  |  | # $name is already packed format (inet_xton) | 
| 1915 | 42 | 100 |  |  |  | 581 | return 1 if $ipn eq $name; | 
| 1916 |  |  |  |  |  |  |  | 
| 1917 |  |  |  |  |  |  | } elsif ( ! $ipn and $type == GEN_DNS ) { | 
| 1918 | 225 |  |  |  |  | 510 | $name =~s/\s+$//; $name =~s/^\s+//; | 
|  | 225 |  |  |  |  | 513 |  | 
| 1919 | 225 |  |  |  |  | 325 | $alt_dnsNames++; | 
| 1920 | 225 | 100 |  |  |  | 563 | $check_name->($name,$identity,$scheme->{wildcards_in_alt},$publicsuffix) | 
| 1921 |  |  |  |  |  |  | and return 1; | 
| 1922 |  |  |  |  |  |  | } | 
| 1923 |  |  |  |  |  |  | } | 
| 1924 |  |  |  |  |  |  |  | 
| 1925 | 122 | 100 | 66 |  |  | 824 | if ( $scheme->{check_cn} eq 'always' or | 
|  |  |  | 100 |  |  |  |  | 
| 1926 |  |  |  |  |  |  | $scheme->{check_cn} eq 'when_only' and !$alt_dnsNames ) { | 
| 1927 | 108 | 100 |  |  |  | 256 | if ( ! $ipn ) { | 
|  |  | 50 |  |  |  |  |  | 
| 1928 | 88 | 100 |  |  |  | 222 | $check_name->($commonName,$identity,$scheme->{wildcards_in_cn},$publicsuffix) | 
| 1929 |  |  |  |  |  |  | and return 1; | 
| 1930 |  |  |  |  |  |  | } elsif ( $scheme->{ip_in_cn} ) { | 
| 1931 | 20 | 100 |  |  |  | 48 | if ( $identity eq $commonName ) { | 
| 1932 |  |  |  |  |  |  | return 1 if | 
| 1933 |  |  |  |  |  |  | $scheme->{ip_in_cn} == 4 ? length($ipn) == 4 : | 
| 1934 | 5 | 0 |  |  |  | 41 | $scheme->{ip_in_cn} == 6 ? length($ipn) == 16 : | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 1935 |  |  |  |  |  |  | 1; | 
| 1936 |  |  |  |  |  |  | } | 
| 1937 |  |  |  |  |  |  | } | 
| 1938 |  |  |  |  |  |  | } | 
| 1939 |  |  |  |  |  |  |  | 
| 1940 | 75 |  |  |  |  | 793 | return 0; # no match | 
| 1941 |  |  |  |  |  |  | } | 
| 1942 |  |  |  |  |  |  | } | 
| 1943 |  |  |  |  |  |  |  | 
| 1944 |  |  |  |  |  |  | sub verify_hostname { | 
| 1945 | 41 |  |  | 41 | 1 | 1797 | my $self = shift; | 
| 1946 | 41 |  |  |  |  | 68 | my $host = shift; | 
| 1947 | 41 |  |  |  |  | 114 | my $cert = $self->peer_certificate; | 
| 1948 | 41 |  |  |  |  | 105 | return verify_hostname_of_cert( $host,$cert,@_ ); | 
| 1949 |  |  |  |  |  |  | } | 
| 1950 |  |  |  |  |  |  |  | 
| 1951 |  |  |  |  |  |  |  | 
| 1952 |  |  |  |  |  |  | sub get_servername { | 
| 1953 | 8 |  |  | 8 | 1 | 151 | my $self = shift; | 
| 1954 | 8 |  | 33 |  |  | 16 | return ${*$self}{_SSL_servername} ||= do { | 
|  | 8 |  |  |  |  | 78 |  | 
| 1955 | 8 | 50 |  |  |  | 41 | my $ssl = $self->_get_ssl_object or return; | 
| 1956 | 8 |  |  |  |  | 69 | Net::SSLeay::get_servername($ssl); | 
| 1957 |  |  |  |  |  |  | }; | 
| 1958 |  |  |  |  |  |  | } | 
| 1959 |  |  |  |  |  |  |  | 
| 1960 |  |  |  |  |  |  | sub get_fingerprint_bin { | 
| 1961 | 22 |  |  | 22 | 1 | 61 | my ($self,$algo,$cert,$key_only) = @_; | 
| 1962 | 22 |  | 66 |  |  | 145 | $cert ||= $self->peer_certificate; | 
| 1963 | 22 | 100 | 50 |  |  | 164 | return $key_only | 
|  |  |  | 50 |  |  |  |  | 
| 1964 |  |  |  |  |  |  | ? Net::SSLeay::X509_pubkey_digest($cert, $algo2digest->($algo || 'sha256')) | 
| 1965 |  |  |  |  |  |  | : Net::SSLeay::X509_digest($cert, $algo2digest->($algo || 'sha256')); | 
| 1966 |  |  |  |  |  |  | } | 
| 1967 |  |  |  |  |  |  |  | 
| 1968 |  |  |  |  |  |  | sub get_fingerprint { | 
| 1969 | 22 |  |  | 22 | 1 | 330 | my ($self,$algo,$cert,$key_only) = @_; | 
| 1970 | 22 |  | 100 |  |  | 101 | $algo ||= 'sha256'; | 
| 1971 | 22 | 50 |  |  |  | 80 | my $fp = get_fingerprint_bin($self,$algo,$cert,$key_only) or return; | 
| 1972 | 22 | 100 |  |  |  | 327 | return $algo.'$'.($key_only ? 'pub$':'').unpack('H*',$fp); | 
| 1973 |  |  |  |  |  |  | } | 
| 1974 |  |  |  |  |  |  |  | 
| 1975 |  |  |  |  |  |  | sub get_cipher { | 
| 1976 | 12 |  | 50 | 12 | 1 | 92 | my $ssl = shift()->_get_ssl_object || return; | 
| 1977 | 12 |  |  |  |  | 79 | return Net::SSLeay::get_cipher($ssl); | 
| 1978 |  |  |  |  |  |  | } | 
| 1979 |  |  |  |  |  |  |  | 
| 1980 |  |  |  |  |  |  | sub get_sslversion { | 
| 1981 | 28 |  | 50 | 28 | 1 | 420 | my $ssl = shift()->_get_ssl_object || return; | 
| 1982 | 28 | 50 |  |  |  | 126 | my $version = Net::SSLeay::version($ssl) or return; | 
| 1983 |  |  |  |  |  |  | return | 
| 1984 | 28 | 0 |  |  |  | 354 | $version == 0x0304 ? 'TLSv1_3' : | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 1985 |  |  |  |  |  |  | $version == 0x0303 ? 'TLSv1_2' : | 
| 1986 |  |  |  |  |  |  | $version == 0x0302 ? 'TLSv1_1' : | 
| 1987 |  |  |  |  |  |  | $version == 0x0301 ? 'TLSv1'   : | 
| 1988 |  |  |  |  |  |  | $version == 0x0300 ? 'SSLv3'   : | 
| 1989 |  |  |  |  |  |  | $version == 0x0002 ? 'SSLv2'   : | 
| 1990 |  |  |  |  |  |  | $version == 0xfeff ? 'DTLS1'   : | 
| 1991 |  |  |  |  |  |  | undef; | 
| 1992 |  |  |  |  |  |  | } | 
| 1993 |  |  |  |  |  |  |  | 
| 1994 |  |  |  |  |  |  | sub get_sslversion_int { | 
| 1995 | 0 |  | 0 | 0 | 1 | 0 | my $ssl = shift()->_get_ssl_object || return; | 
| 1996 | 0 |  |  |  |  | 0 | return Net::SSLeay::version($ssl); | 
| 1997 |  |  |  |  |  |  | } | 
| 1998 |  |  |  |  |  |  |  | 
| 1999 |  |  |  |  |  |  | sub get_session_reused { | 
| 2000 | 3 |  | 50 | 3 | 1 | 20 | return Net::SSLeay::session_reused( | 
| 2001 |  |  |  |  |  |  | shift()->_get_ssl_object || return); | 
| 2002 |  |  |  |  |  |  | } | 
| 2003 |  |  |  |  |  |  |  | 
| 2004 |  |  |  |  |  |  | if ($can_ocsp) { | 
| 2005 | 80 |  |  | 80 |  | 778 | no warnings 'once'; | 
|  | 80 |  |  |  |  | 173 |  | 
|  | 80 |  |  |  |  | 135893 |  | 
| 2006 |  |  |  |  |  |  | *ocsp_resolver = sub { | 
| 2007 | 4 |  |  | 4 |  | 839 | my $self = shift; | 
| 2008 | 4 |  | 50 |  |  | 16 | my $ssl = $self->_get_ssl_object || return; | 
| 2009 | 4 |  |  |  |  | 10 | my $ctx = ${*$self}{_SSL_ctx}; | 
|  | 4 |  |  |  |  | 12 |  | 
| 2010 |  |  |  |  |  |  | return IO::Socket::SSL::OCSP_Resolver->new( | 
| 2011 |  |  |  |  |  |  | $ssl, | 
| 2012 |  |  |  |  |  |  | $ctx->{ocsp_cache} ||= IO::Socket::SSL::OCSP_Cache->new, | 
| 2013 |  |  |  |  |  |  | $ctx->{ocsp_mode} & SSL_OCSP_FAIL_HARD, | 
| 2014 |  |  |  |  |  |  | @_ ? \@_ : | 
| 2015 | 4 | 100 | 66 |  |  | 45 | $ctx->{ocsp_mode} & SSL_OCSP_FULL_CHAIN ? [ $self->peer_certificates ]: | 
|  |  | 50 |  |  |  |  |  | 
| 2016 |  |  |  |  |  |  | [ $self->peer_certificate ] | 
| 2017 |  |  |  |  |  |  | ); | 
| 2018 |  |  |  |  |  |  | }; | 
| 2019 |  |  |  |  |  |  | } | 
| 2020 |  |  |  |  |  |  |  | 
| 2021 |  |  |  |  |  |  | sub errstr { | 
| 2022 | 49 |  |  | 49 | 1 | 102 | my $self = shift; | 
| 2023 | 49 |  | 33 |  |  | 254 | my $oe = ref($self) && ${*$self}{_SSL_last_err}; | 
| 2024 | 49 | 50 | 0 |  |  | 251 | return $oe ? $oe->[0] : $SSL_ERROR || ''; | 
| 2025 |  |  |  |  |  |  | } | 
| 2026 |  |  |  |  |  |  |  | 
| 2027 |  |  |  |  |  |  | sub fatal_ssl_error { | 
| 2028 | 48 |  |  | 48 | 0 | 150 | my $self = shift; | 
| 2029 | 48 |  |  |  |  | 96 | my $error_trap = ${*$self}{'_SSL_arguments'}->{'SSL_error_trap'}; | 
|  | 48 |  |  |  |  | 180 |  | 
| 2030 | 48 |  |  |  |  | 185 | $@ = $self->errstr; | 
| 2031 | 48 |  |  |  |  | 141 | my $saved_error = $SSL_ERROR; | 
| 2032 | 48 | 100 | 66 |  |  | 242 | if (defined $error_trap and ref($error_trap) eq 'CODE') { | 
|  |  | 100 | 66 |  |  |  |  | 
| 2033 | 1 |  |  |  |  | 3 | $error_trap->($self, $self->errstr()."\n".$self->get_ssleay_error()); | 
| 2034 | 47 |  |  |  |  | 322 | } elsif ( ${*$self}{'_SSL_ioclass_upgraded'} | 
| 2035 | 8 |  |  |  |  | 60 | || ${*$self}{_SSL_arguments}{SSL_keepSocketOnError}) { | 
| 2036 |  |  |  |  |  |  | # downgrade only | 
| 2037 | 39 | 50 |  |  |  | 116 | $DEBUG>=3 && DEBUG('downgrading SSL only, not closing socket' ); | 
| 2038 | 39 |  |  |  |  | 164 | $self->stop_SSL; | 
| 2039 |  |  |  |  |  |  | } else { | 
| 2040 |  |  |  |  |  |  | # kill socket | 
| 2041 | 8 |  |  |  |  | 148 | $self->close | 
| 2042 |  |  |  |  |  |  | } | 
| 2043 | 48 | 50 |  |  |  | 1151 | $SSL_ERROR = $saved_error if $saved_error; | 
| 2044 | 48 |  |  |  |  | 320 | return; | 
| 2045 |  |  |  |  |  |  | } | 
| 2046 |  |  |  |  |  |  |  | 
| 2047 |  |  |  |  |  |  | sub get_ssleay_error { | 
| 2048 |  |  |  |  |  |  | #Net::SSLeay will print out the errors itself unless we explicitly | 
| 2049 |  |  |  |  |  |  | #undefine $Net::SSLeay::trace while running print_errs() | 
| 2050 | 1 |  |  | 1 | 0 | 16 | local $Net::SSLeay::trace; | 
| 2051 | 1 |  | 50 |  |  | 22 | return Net::SSLeay::print_errs('SSL error: ') || ''; | 
| 2052 |  |  |  |  |  |  | } | 
| 2053 |  |  |  |  |  |  |  | 
| 2054 |  |  |  |  |  |  | # internal errors, e.g. unsupported features, hostname check failed etc | 
| 2055 |  |  |  |  |  |  | # _SSL_last_err contains severity so that on error chains we can decide if one | 
| 2056 |  |  |  |  |  |  | # error should replace the previous one or if this is just a less specific | 
| 2057 |  |  |  |  |  |  | # follow-up error, e.g. configuration failed because certificate failed because | 
| 2058 |  |  |  |  |  |  | # hostname check went wrong: | 
| 2059 |  |  |  |  |  |  | # 0 - fallback errors | 
| 2060 |  |  |  |  |  |  | # 4 - errors bubbled up from OpenSSL (sub error, r/w error) | 
| 2061 |  |  |  |  |  |  | # 5 - hostname or OCSP verification failed | 
| 2062 |  |  |  |  |  |  | # 9 - fatal problems, e.g. missing feature, no fileno... | 
| 2063 |  |  |  |  |  |  | # _SSL_last_err and SSL_ERROR are only replaced if the error has a higher | 
| 2064 |  |  |  |  |  |  | # severity than the previous one | 
| 2065 |  |  |  |  |  |  |  | 
| 2066 |  |  |  |  |  |  | sub _internal_error { | 
| 2067 | 83 |  |  | 83 |  | 538 | my ($self, $error, $severity) = @_; | 
| 2068 | 83 |  |  |  |  | 512 | $error = dualvar( -1, $error ); | 
| 2069 | 83 | 100 | 100 |  |  | 581 | $self = $CURRENT_SSL_OBJECT if !ref($self) && $CURRENT_SSL_OBJECT; | 
| 2070 | 83 | 100 |  |  |  | 281 | if (ref($self)) { | 
| 2071 | 78 |  |  |  |  | 147 | my $oe = ${*$self}{_SSL_last_err}; | 
|  | 78 |  |  |  |  | 410 |  | 
| 2072 | 78 | 100 | 100 |  |  | 553 | if (!$oe || $oe->[1] <= $severity) { | 
| 2073 | 50 |  |  |  |  | 227 | ${*$self}{_SSL_last_err} = [$error,$severity]; | 
|  | 50 |  |  |  |  | 273 |  | 
| 2074 | 50 |  |  |  |  | 172 | $SSL_ERROR = $error; | 
| 2075 | 50 | 50 |  |  |  | 193 | $DEBUG && DEBUG("local error: $error"); | 
| 2076 |  |  |  |  |  |  | } else { | 
| 2077 | 28 | 50 |  |  |  | 99 | $DEBUG && DEBUG("ignoring less severe local error '$error', keep '$oe->[0]'"); | 
| 2078 |  |  |  |  |  |  | } | 
| 2079 |  |  |  |  |  |  | } else { | 
| 2080 | 5 |  |  |  |  | 29 | $SSL_ERROR = $error; | 
| 2081 | 5 | 50 |  |  |  | 21 | $DEBUG && DEBUG("global error: $error"); | 
| 2082 |  |  |  |  |  |  | } | 
| 2083 | 83 |  |  |  |  | 304 | return; | 
| 2084 |  |  |  |  |  |  | } | 
| 2085 |  |  |  |  |  |  |  | 
| 2086 |  |  |  |  |  |  | # OpenSSL errors | 
| 2087 |  |  |  |  |  |  | sub error { | 
| 2088 | 52 |  |  | 52 | 1 | 367 | my ($self, $error) = @_; | 
| 2089 | 52 |  |  |  |  | 135 | my @err; | 
| 2090 | 52 |  |  |  |  | 446 | while ( my $err = Net::SSLeay::ERR_get_error()) { | 
| 2091 | 49 |  |  |  |  | 764 | push @err, Net::SSLeay::ERR_error_string($err); | 
| 2092 | 49 | 50 |  |  |  | 339 | $DEBUG>=2 && DEBUG( $error."\n".$self->get_ssleay_error()); | 
| 2093 |  |  |  |  |  |  | } | 
| 2094 | 52 | 100 |  |  |  | 366 | $error .= ' '.join(' ',@err) if @err; | 
| 2095 | 52 | 50 |  |  |  | 358 | return $self->_internal_error($error,4) if $error; | 
| 2096 | 0 |  |  |  |  | 0 | return; | 
| 2097 |  |  |  |  |  |  | } | 
| 2098 |  |  |  |  |  |  |  | 
| 2099 |  |  |  |  |  |  | sub _errstack { | 
| 2100 | 5 |  |  | 5 |  | 14 | my @err; | 
| 2101 | 5 |  |  |  |  | 142 | while (my $err = Net::SSLeay::ERR_get_error()) { | 
| 2102 | 14 |  |  |  |  | 378 | push @err, Net::SSLeay::ERR_error_string($err); | 
| 2103 |  |  |  |  |  |  | } | 
| 2104 | 5 |  |  |  |  | 102 | return @err; | 
| 2105 |  |  |  |  |  |  | } | 
| 2106 |  |  |  |  |  |  |  | 
| 2107 | 7 |  |  | 7 | 0 | 734 | sub can_client_sni { return $can_client_sni } | 
| 2108 | 6 |  |  | 6 | 0 | 9870 | sub can_server_sni { return $can_server_sni } | 
| 2109 | 2 |  |  | 2 | 0 | 16 | sub can_multi_cert { return $can_multi_cert } | 
| 2110 | 2 |  |  | 2 | 0 | 2912 | sub can_npn        { return $can_npn } | 
| 2111 | 2 |  |  | 2 | 0 | 3042 | sub can_alpn       { return $can_alpn } | 
| 2112 | 2 |  |  | 2 | 0 | 2754 | sub can_ecdh       { return $can_ecdh } | 
| 2113 | 4 |  |  | 4 | 0 | 264 | sub can_ipv6       { return CAN_IPV6 } | 
| 2114 | 1 |  |  | 1 | 0 | 10 | sub can_ocsp       { return $can_ocsp } | 
| 2115 | 1 |  |  | 1 | 0 | 1470 | sub can_ticket_keycb { return $can_tckt_keycb } | 
| 2116 | 0 |  |  | 0 | 0 | 0 | sub can_pha        { return $can_pha } | 
| 2117 | 1 |  | 50 | 1 | 0 | 14 | sub can_partial_chain { return $check_partial_chain && 1 } | 
| 2118 | 0 |  |  | 0 | 0 | 0 | sub can_ciphersuites { return $can_ciphersuites } | 
| 2119 |  |  |  |  |  |  |  | 
| 2120 |  |  |  |  |  |  | sub DESTROY { | 
| 2121 | 289 | 50 |  | 289 |  | 78868219 | my $self = shift or return; | 
| 2122 | 289 | 100 |  |  |  | 704 | if (my $ssl = ${*$self}{_SSL_object}) { | 
|  | 289 |  |  |  |  | 2309 |  | 
| 2123 | 197 |  |  |  |  | 1143 | delete $SSL_OBJECT{$ssl}; | 
| 2124 | 197 | 50 | 33 |  |  | 1018 | if (!$use_threads or delete $CREATED_IN_THIS_THREAD{$ssl}) { | 
| 2125 | 197 |  |  |  |  | 1511 | $self->close(_SSL_in_DESTROY => 1, SSL_no_shutdown => 1); | 
| 2126 |  |  |  |  |  |  | } | 
| 2127 |  |  |  |  |  |  | } | 
| 2128 | 289 |  |  |  |  | 1072 | delete @{*$self}{@all_my_keys}; | 
|  | 289 |  |  |  |  | 18657 |  | 
| 2129 |  |  |  |  |  |  | } | 
| 2130 |  |  |  |  |  |  |  | 
| 2131 |  |  |  |  |  |  |  | 
| 2132 |  |  |  |  |  |  | #######Extra Backwards Compatibility Functionality####### | 
| 2133 | 1 |  |  | 1 | 1 | 104 | sub socket_to_SSL { IO::Socket::SSL->start_SSL(@_); } | 
| 2134 | 1 |  |  | 1 | 1 | 4711 | sub socketToSSL { IO::Socket::SSL->start_SSL(@_); } | 
| 2135 | 0 |  |  | 0 | 1 | 0 | sub kill_socket { shift->close } | 
| 2136 |  |  |  |  |  |  |  | 
| 2137 | 1 |  |  | 1 | 1 | 32 | sub issuer_name { return(shift()->peer_certificate("issuer")) } | 
| 2138 | 1 |  |  | 1 | 1 | 5 | sub subject_name { return(shift()->peer_certificate("subject")) } | 
| 2139 | 0 |  |  | 0 | 1 | 0 | sub get_peer_certificate { return shift() } | 
| 2140 |  |  |  |  |  |  |  | 
| 2141 |  |  |  |  |  |  | sub context_init { | 
| 2142 | 2 | 50 |  | 2 | 1 | 3660 | return($GLOBAL_SSL_ARGS = (ref($_[0]) eq 'HASH') ? $_[0] : {@_}); | 
| 2143 |  |  |  |  |  |  | } | 
| 2144 |  |  |  |  |  |  |  | 
| 2145 |  |  |  |  |  |  | sub set_default_context { | 
| 2146 | 1 |  |  | 1 | 1 | 135 | $GLOBAL_SSL_ARGS->{'SSL_reuse_ctx'} = shift; | 
| 2147 |  |  |  |  |  |  | } | 
| 2148 |  |  |  |  |  |  |  | 
| 2149 |  |  |  |  |  |  | sub set_default_session_cache { | 
| 2150 | 0 |  |  | 0 | 1 | 0 | $GLOBAL_SSL_ARGS->{SSL_session_cache} = shift; | 
| 2151 |  |  |  |  |  |  | } | 
| 2152 |  |  |  |  |  |  |  | 
| 2153 |  |  |  |  |  |  |  | 
| 2154 |  |  |  |  |  |  | { | 
| 2155 |  |  |  |  |  |  | my $set_defaults = sub { | 
| 2156 |  |  |  |  |  |  | my $args = shift; | 
| 2157 |  |  |  |  |  |  | for(my $i=0;$i<@$args;$i+=2 ) { | 
| 2158 |  |  |  |  |  |  | my ($k,$v) = @{$args}[$i,$i+1]; | 
| 2159 |  |  |  |  |  |  | if ( $k =~m{^SSL_} ) { | 
| 2160 |  |  |  |  |  |  | $_->{$k} = $v for(@_); | 
| 2161 |  |  |  |  |  |  | } elsif ( $k =~m{^(name|scheme)$} ) { | 
| 2162 |  |  |  |  |  |  | $_->{"SSL_verifycn_$k"} = $v for (@_); | 
| 2163 |  |  |  |  |  |  | } elsif ( $k =~m{^(callback|mode)$} ) { | 
| 2164 |  |  |  |  |  |  | $_->{"SSL_verify_$k"} = $v for(@_); | 
| 2165 |  |  |  |  |  |  | } else { | 
| 2166 |  |  |  |  |  |  | $_->{"SSL_$k"} = $v for(@_); | 
| 2167 |  |  |  |  |  |  | } | 
| 2168 |  |  |  |  |  |  | } | 
| 2169 |  |  |  |  |  |  | }; | 
| 2170 |  |  |  |  |  |  | sub set_defaults { | 
| 2171 | 0 |  |  | 0 | 1 | 0 | my %args = @_; | 
| 2172 | 0 |  |  |  |  | 0 | $set_defaults->(\@_, | 
| 2173 |  |  |  |  |  |  | $GLOBAL_SSL_ARGS, | 
| 2174 |  |  |  |  |  |  | $GLOBAL_SSL_CLIENT_ARGS, | 
| 2175 |  |  |  |  |  |  | $GLOBAL_SSL_SERVER_ARGS | 
| 2176 |  |  |  |  |  |  | ); | 
| 2177 |  |  |  |  |  |  | } | 
| 2178 |  |  |  |  |  |  | { # deprecated API | 
| 2179 | 80 |  |  | 80 |  | 783 | no warnings; | 
|  | 80 |  |  |  |  | 155 |  | 
|  | 80 |  |  |  |  | 59780 |  | 
| 2180 |  |  |  |  |  |  | *set_ctx_defaults = \&set_defaults; | 
| 2181 |  |  |  |  |  |  | } | 
| 2182 |  |  |  |  |  |  | sub set_client_defaults { | 
| 2183 | 0 |  |  | 0 | 1 | 0 | my %args = @_; | 
| 2184 | 0 |  |  |  |  | 0 | $set_defaults->(\@_, $GLOBAL_SSL_CLIENT_ARGS ); | 
| 2185 |  |  |  |  |  |  | } | 
| 2186 |  |  |  |  |  |  | sub set_server_defaults { | 
| 2187 | 0 |  |  | 0 | 1 | 0 | my %args = @_; | 
| 2188 | 0 |  |  |  |  | 0 | $set_defaults->(\@_, $GLOBAL_SSL_SERVER_ARGS ); | 
| 2189 |  |  |  |  |  |  | } | 
| 2190 |  |  |  |  |  |  | } | 
| 2191 |  |  |  |  |  |  |  | 
| 2192 |  |  |  |  |  |  | sub set_args_filter_hack { | 
| 2193 | 0 |  |  | 0 | 1 | 0 | my $sub = shift; | 
| 2194 | 0 | 0 |  |  |  | 0 | if ( ref $sub ) { | 
|  |  | 0 |  |  |  |  |  | 
| 2195 | 0 |  |  |  |  | 0 | $FILTER_SSL_ARGS = $sub; | 
| 2196 |  |  |  |  |  |  | } elsif ( $sub eq 'use_defaults' ) { | 
| 2197 |  |  |  |  |  |  | # override args with defaults | 
| 2198 |  |  |  |  |  |  | $FILTER_SSL_ARGS = sub { | 
| 2199 | 0 |  |  | 0 |  | 0 | my ($is_server,$args) = @_; | 
| 2200 | 0 | 0 |  |  |  | 0 | %$args = ( %$args, $is_server | 
| 2201 |  |  |  |  |  |  | ? ( %DEFAULT_SSL_SERVER_ARGS, %$GLOBAL_SSL_SERVER_ARGS ) | 
| 2202 |  |  |  |  |  |  | : ( %DEFAULT_SSL_CLIENT_ARGS, %$GLOBAL_SSL_CLIENT_ARGS ) | 
| 2203 |  |  |  |  |  |  | ); | 
| 2204 |  |  |  |  |  |  | } | 
| 2205 | 0 |  |  |  |  | 0 | } | 
| 2206 |  |  |  |  |  |  | } | 
| 2207 |  |  |  |  |  |  |  | 
| 2208 |  |  |  |  |  |  | sub next_proto_negotiated { | 
| 2209 | 2 |  |  | 2 | 1 | 731 | my $self = shift; | 
| 2210 | 2 | 50 |  |  |  | 15 | return $self->_internal_error("NPN not supported in Net::SSLeay",9) if ! $can_npn; | 
| 2211 | 2 |  | 50 |  |  | 36 | my $ssl = $self->_get_ssl_object || return; | 
| 2212 | 2 |  |  |  |  | 22 | return Net::SSLeay::P_next_proto_negotiated($ssl); | 
| 2213 |  |  |  |  |  |  | } | 
| 2214 |  |  |  |  |  |  |  | 
| 2215 |  |  |  |  |  |  | sub alpn_selected { | 
| 2216 | 2 |  |  | 2 | 1 | 115 | my $self = shift; | 
| 2217 | 2 | 50 |  |  |  | 13 | return $self->_internal_error("ALPN not supported in Net::SSLeay",9) if ! $can_alpn; | 
| 2218 | 2 |  | 50 |  |  | 17 | my $ssl = $self->_get_ssl_object || return; | 
| 2219 | 2 |  |  |  |  | 15 | return Net::SSLeay::P_alpn_selected($ssl); | 
| 2220 |  |  |  |  |  |  | } | 
| 2221 |  |  |  |  |  |  |  | 
| 2222 |  |  |  |  |  |  | sub opened { | 
| 2223 | 5 |  |  | 5 | 1 | 1084 | my $self = shift; | 
| 2224 | 5 |  | 66 |  |  | 23 | return IO::Handle::opened($self) && ${*$self}{'_SSL_opened'}; | 
| 2225 |  |  |  |  |  |  | } | 
| 2226 |  |  |  |  |  |  |  | 
| 2227 |  |  |  |  |  |  | sub opening { | 
| 2228 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 2229 | 0 |  |  |  |  | 0 | return ${*$self}{'_SSL_opening'}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2230 |  |  |  |  |  |  | } | 
| 2231 |  |  |  |  |  |  |  | 
| 2232 | 0 |  |  | 0 | 0 | 0 | sub want_read  { shift->errstr == SSL_WANT_READ } | 
| 2233 | 0 |  |  | 0 | 0 | 0 | sub want_write { shift->errstr == SSL_WANT_WRITE } | 
| 2234 |  |  |  |  |  |  |  | 
| 2235 |  |  |  |  |  |  |  | 
| 2236 |  |  |  |  |  |  | #Redundant IO::Handle functionality | 
| 2237 | 1 |  |  | 1 | 1 | 894 | sub getline { return(scalar shift->readline()) } | 
| 2238 |  |  |  |  |  |  | sub getlines { | 
| 2239 | 1 | 50 |  | 1 | 1 | 12 | return(shift->readline()) if wantarray(); | 
| 2240 | 0 |  |  |  |  | 0 | croak("Use of getlines() not allowed in scalar context"); | 
| 2241 |  |  |  |  |  |  | } | 
| 2242 |  |  |  |  |  |  |  | 
| 2243 |  |  |  |  |  |  | #Useless IO::Handle functionality | 
| 2244 | 0 |  |  | 0 | 1 | 0 | sub truncate { croak("Use of truncate() not allowed with SSL") } | 
| 2245 | 0 |  |  | 0 | 1 | 0 | sub stat     { croak("Use of stat() not allowed with SSL" ) } | 
| 2246 | 0 |  |  | 0 | 1 | 0 | sub setbuf   { croak("Use of setbuf() not allowed with SSL" ) } | 
| 2247 | 0 |  |  | 0 | 1 | 0 | sub setvbuf  { croak("Use of setvbuf() not allowed with SSL" ) } | 
| 2248 | 0 |  |  | 0 | 1 | 0 | sub fdopen   { croak("Use of fdopen() not allowed with SSL" ) } | 
| 2249 |  |  |  |  |  |  |  | 
| 2250 |  |  |  |  |  |  | #Unsupported socket functionality | 
| 2251 | 0 |  |  | 0 | 1 | 0 | sub ungetc { croak("Use of ungetc() not implemented in IO::Socket::SSL") } | 
| 2252 | 0 |  |  | 0 | 1 | 0 | sub send   { croak("Use of send() not implemented in IO::Socket::SSL; use print/printf/syswrite instead") } | 
| 2253 | 0 |  |  | 0 | 1 | 0 | sub recv   { croak("Use of recv() not implemented in IO::Socket::SSL; use read/sysread instead") } | 
| 2254 |  |  |  |  |  |  |  | 
| 2255 |  |  |  |  |  |  | package IO::Socket::SSL::SSL_HANDLE; | 
| 2256 | 80 |  |  | 80 |  | 687 | use strict; | 
|  | 80 |  |  |  |  | 239 |  | 
|  | 80 |  |  |  |  | 2434 |  | 
| 2257 | 80 |  |  | 80 |  | 519 | use Errno 'EBADF'; | 
|  | 80 |  |  |  |  | 210 |  | 
|  | 80 |  |  |  |  | 30628 |  | 
| 2258 |  |  |  |  |  |  | *weaken = *IO::Socket::SSL::weaken; | 
| 2259 |  |  |  |  |  |  |  | 
| 2260 |  |  |  |  |  |  | sub TIEHANDLE { | 
| 2261 | 247 |  |  | 247 |  | 1364 | my ($class, $handle) = @_; | 
| 2262 | 247 |  |  |  |  | 1379 | weaken($handle); | 
| 2263 | 247 |  |  |  |  | 1917 | bless \$handle, $class; | 
| 2264 |  |  |  |  |  |  | } | 
| 2265 |  |  |  |  |  |  |  | 
| 2266 | 6036 |  |  | 6036 |  | 10049735 | sub READ     { ${shift()}->sysread(@_) } | 
|  | 6036 |  |  |  |  | 13926 |  | 
| 2267 | 81 |  |  | 81 |  | 14727 | sub READLINE { ${shift()}->readline(@_) } | 
|  | 81 |  |  |  |  | 658 |  | 
| 2268 | 1 |  |  | 1 |  | 857 | sub GETC     { ${shift()}->getc(@_) } | 
|  | 1 |  |  |  |  | 5 |  | 
| 2269 |  |  |  |  |  |  |  | 
| 2270 | 47 |  |  | 47 |  | 904 | sub PRINT    { ${shift()}->print(@_) } | 
|  | 47 |  |  |  |  | 421 |  | 
| 2271 | 1 |  |  | 1 |  | 9 | sub PRINTF   { ${shift()}->printf(@_) } | 
|  | 1 |  |  |  |  | 5 |  | 
| 2272 | 7168 |  |  | 7168 |  | 11653868 | sub WRITE    { ${shift()}->syswrite(@_) } | 
|  | 7168 |  |  |  |  | 15365 |  | 
| 2273 |  |  |  |  |  |  |  | 
| 2274 | 7166 |  |  | 7166 |  | 265932 | sub FILENO   { ${shift()}->fileno(@_) } | 
|  | 7166 |  |  |  |  | 16589 |  | 
| 2275 |  |  |  |  |  |  |  | 
| 2276 | 0 |  |  | 0 |  | 0 | sub TELL     { $! = EBADF; return -1 } | 
|  | 0 |  |  |  |  | 0 |  | 
| 2277 | 0 |  |  | 0 |  | 0 | sub BINMODE  { return 0 }  # not perfect, but better than not implementing the method | 
| 2278 |  |  |  |  |  |  |  | 
| 2279 |  |  |  |  |  |  | sub CLOSE {                          #<---- Do not change this function! | 
| 2280 | 36 |  |  | 36 |  | 10687 | my $ssl = ${$_[0]}; | 
|  | 36 |  |  |  |  | 143 |  | 
| 2281 | 36 |  |  |  |  | 104 | local @_; | 
| 2282 | 36 |  |  |  |  | 182 | $ssl->close(); | 
| 2283 |  |  |  |  |  |  | } | 
| 2284 |  |  |  |  |  |  |  | 
| 2285 |  |  |  |  |  |  |  | 
| 2286 |  |  |  |  |  |  | package IO::Socket::SSL::SSL_Context; | 
| 2287 | 80 |  |  | 80 |  | 759 | use Carp; | 
|  | 80 |  |  |  |  | 225 |  | 
|  | 80 |  |  |  |  | 6142 |  | 
| 2288 | 80 |  |  | 80 |  | 641 | use strict; | 
|  | 80 |  |  |  |  | 209 |  | 
|  | 80 |  |  |  |  | 4505 |  | 
| 2289 |  |  |  |  |  |  |  | 
| 2290 |  |  |  |  |  |  | my %CTX_CREATED_IN_THIS_THREAD; | 
| 2291 |  |  |  |  |  |  | *DEBUG = *IO::Socket::SSL::DEBUG; | 
| 2292 |  |  |  |  |  |  | *_errstack = \&IO::Socket::SSL::_errstack; | 
| 2293 |  |  |  |  |  |  |  | 
| 2294 | 80 |  |  | 80 |  | 529 | use constant SSL_MODE_ENABLE_PARTIAL_WRITE => 1; | 
|  | 80 |  |  |  |  | 223 |  | 
|  | 80 |  |  |  |  | 5913 |  | 
| 2295 | 80 |  |  | 80 |  | 587 | use constant SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER => 2; | 
|  | 80 |  |  |  |  | 237 |  | 
|  | 80 |  |  |  |  | 5528 |  | 
| 2296 |  |  |  |  |  |  |  | 
| 2297 | 80 |  |  | 80 |  | 558 | use constant FILETYPE_PEM => Net::SSLeay::FILETYPE_PEM(); | 
|  | 80 |  |  |  |  | 183 |  | 
|  | 80 |  |  |  |  | 2651 |  | 
| 2298 | 80 |  |  | 80 |  | 13589 | use constant FILETYPE_ASN1 => Net::SSLeay::FILETYPE_ASN1(); | 
|  | 80 |  |  |  |  | 1827 |  | 
|  | 80 |  |  |  |  | 684 |  | 
| 2299 |  |  |  |  |  |  |  | 
| 2300 |  |  |  |  |  |  | my $DEFAULT_SSL_OP = &Net::SSLeay::OP_ALL | 
| 2301 |  |  |  |  |  |  | | &Net::SSLeay::OP_SINGLE_DH_USE | 
| 2302 |  |  |  |  |  |  | | ($can_ecdh ? &Net::SSLeay::OP_SINGLE_ECDH_USE : 0); | 
| 2303 |  |  |  |  |  |  |  | 
| 2304 |  |  |  |  |  |  | # Note that the final object will actually be a reference to the scalar | 
| 2305 |  |  |  |  |  |  | # (C-style pointer) returned by Net::SSLeay::CTX_*_new() so that | 
| 2306 |  |  |  |  |  |  | # it can be blessed. | 
| 2307 |  |  |  |  |  |  | sub new { | 
| 2308 | 284 |  |  | 284 |  | 17206 | my $class = shift; | 
| 2309 |  |  |  |  |  |  | #DEBUG( "$class @_" ); | 
| 2310 | 284 | 100 |  |  |  | 2566 | my $arg_hash = (ref($_[0]) eq 'HASH') ? $_[0] : {@_}; | 
| 2311 |  |  |  |  |  |  |  | 
| 2312 | 284 |  |  |  |  | 1370 | my $is_server = $arg_hash->{SSL_server}; | 
| 2313 | 284 | 100 |  |  |  | 9830 | my %defaults = $is_server | 
| 2314 |  |  |  |  |  |  | ? (%DEFAULT_SSL_SERVER_ARGS, %$GLOBAL_SSL_ARGS, %$GLOBAL_SSL_SERVER_ARGS) | 
| 2315 |  |  |  |  |  |  | : (%DEFAULT_SSL_CLIENT_ARGS, %$GLOBAL_SSL_ARGS, %$GLOBAL_SSL_CLIENT_ARGS); | 
| 2316 | 284 | 100 |  |  |  | 1656 | if ( $defaults{SSL_reuse_ctx} ) { | 
| 2317 |  |  |  |  |  |  | # ignore default context if there are args to override it | 
| 2318 |  |  |  |  |  |  | delete $defaults{SSL_reuse_ctx} | 
| 2319 | 6 | 50 |  |  |  | 24 | if grep { m{^SSL_(?!verifycn_name|hostname)$} } keys %$arg_hash; | 
|  | 22 |  |  |  |  | 70 |  | 
| 2320 |  |  |  |  |  |  | } | 
| 2321 | 284 | 50 |  |  |  | 5468 | %$arg_hash = ( %defaults, %$arg_hash ) if %defaults; | 
| 2322 |  |  |  |  |  |  |  | 
| 2323 | 284 | 100 |  |  |  | 1777 | if (my $ctx = $arg_hash->{'SSL_reuse_ctx'}) { | 
| 2324 | 26 | 100 | 66 |  |  | 240 | if ($ctx->isa('IO::Socket::SSL::SSL_Context') and | 
|  |  | 50 |  |  |  |  |  | 
| 2325 |  |  |  |  |  |  | $ctx->{context}) { | 
| 2326 |  |  |  |  |  |  | # valid context | 
| 2327 | 2 |  |  |  |  | 8 | } elsif ( $ctx = ${*$ctx}{_SSL_ctx} ) { | 
| 2328 |  |  |  |  |  |  | # reuse context from existing SSL object | 
| 2329 |  |  |  |  |  |  | } | 
| 2330 | 26 |  |  |  |  | 98 | return $ctx | 
| 2331 |  |  |  |  |  |  | } | 
| 2332 |  |  |  |  |  |  |  | 
| 2333 |  |  |  |  |  |  | # common problem forgetting to set SSL_use_cert | 
| 2334 |  |  |  |  |  |  | # if client cert is given by user but SSL_use_cert is undef, assume that it | 
| 2335 |  |  |  |  |  |  | # should be set | 
| 2336 | 258 | 100 | 100 |  |  | 5894 | if ( ! $is_server && ! defined $arg_hash->{SSL_use_cert} | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 2337 | 330 |  |  |  |  | 2664 | && ( grep { $arg_hash->{$_} } qw(SSL_cert SSL_cert_file)) | 
| 2338 | 12 |  |  |  |  | 57 | && ( grep { $arg_hash->{$_} } qw(SSL_key SSL_key_file)) ) { | 
| 2339 | 6 |  |  |  |  | 36 | $arg_hash->{SSL_use_cert} = 1 | 
| 2340 |  |  |  |  |  |  | } | 
| 2341 |  |  |  |  |  |  |  | 
| 2342 |  |  |  |  |  |  | # if any of SSL_ca* is set don't set the other SSL_ca* | 
| 2343 |  |  |  |  |  |  | # from defaults | 
| 2344 | 258 | 100 |  |  |  | 1832 | if ( $arg_hash->{SSL_ca} ) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 2345 |  |  |  |  |  |  | $arg_hash->{SSL_ca_file} ||= undef | 
| 2346 |  |  |  |  |  |  | $arg_hash->{SSL_ca_path} ||= undef | 
| 2347 | 32 |  | 50 |  |  | 236 | } elsif ( $arg_hash->{SSL_ca_path} ) { | 
|  |  |  | 33 |  |  |  |  | 
| 2348 |  |  |  |  |  |  | $arg_hash->{SSL_ca_file} ||= undef | 
| 2349 | 0 |  | 0 |  |  | 0 | } elsif ( $arg_hash->{SSL_ca_file} ) { | 
| 2350 | 61 |  | 50 |  |  | 711 | $arg_hash->{SSL_ca_path} ||= undef; | 
| 2351 |  |  |  |  |  |  | } | 
| 2352 |  |  |  |  |  |  |  | 
| 2353 |  |  |  |  |  |  | # add library defaults | 
| 2354 | 258 | 100 |  |  |  | 1572 | $arg_hash->{SSL_use_cert} = $is_server if ! defined $arg_hash->{SSL_use_cert}; | 
| 2355 |  |  |  |  |  |  |  | 
| 2356 |  |  |  |  |  |  |  | 
| 2357 |  |  |  |  |  |  | # Avoid passing undef arguments to Net::SSLeay | 
| 2358 | 258 |  | 66 |  |  | 5010 | defined($arg_hash->{$_}) or delete($arg_hash->{$_}) for(keys %$arg_hash); | 
| 2359 |  |  |  |  |  |  |  | 
| 2360 |  |  |  |  |  |  | # check SSL CA, cert etc arguments | 
| 2361 |  |  |  |  |  |  | # some apps set keys '' to signal that it is not set, replace with undef | 
| 2362 | 258 |  |  |  |  | 1330 | for (qw( SSL_cert SSL_cert_file SSL_key SSL_key_file | 
| 2363 |  |  |  |  |  |  | SSL_ca SSL_ca_file SSL_ca_path | 
| 2364 |  |  |  |  |  |  | SSL_fingerprint )) { | 
| 2365 |  |  |  |  |  |  | $arg_hash->{$_} = undef if defined $arg_hash->{$_} | 
| 2366 | 2064 | 50 | 66 |  |  | 6704 | and $arg_hash->{$_} eq ''; | 
| 2367 |  |  |  |  |  |  | } | 
| 2368 | 258 |  |  |  |  | 875 | for(qw(SSL_cert_file SSL_key_file)) { | 
| 2369 | 516 | 100 |  |  |  | 2200 | defined( my $file = $arg_hash->{$_} ) or next; | 
| 2370 | 136 | 100 |  |  |  | 965 | for my $f (ref($file) eq 'HASH' ? values(%$file):$file ) { | 
| 2371 | 168 | 50 |  |  |  | 10465 | die "$_ $f can't be used: $!" if ! open(my $fh,'<',$f) | 
| 2372 |  |  |  |  |  |  | } | 
| 2373 |  |  |  |  |  |  | } | 
| 2374 |  |  |  |  |  |  |  | 
| 2375 | 258 |  | 100 |  |  | 2600 | my $verify_mode = $arg_hash->{SSL_verify_mode} || 0; | 
| 2376 | 258 | 100 |  |  |  | 1759 | if ( $verify_mode != $Net_SSLeay_VERIFY_NONE) { | 
|  |  | 50 |  |  |  |  |  | 
| 2377 | 93 |  |  |  |  | 276 | for (qw(SSL_ca_file SSL_ca_path)) { | 
| 2378 | 186 |  | 100 |  |  | 1375 | $CHECK_SSL_PATH->($_ => $arg_hash->{$_} || next); | 
| 2379 |  |  |  |  |  |  | } | 
| 2380 |  |  |  |  |  |  | } elsif ( $verify_mode ne '0' ) { | 
| 2381 |  |  |  |  |  |  | # some users use the string 'SSL_VERIFY_PEER' instead of the constant | 
| 2382 | 0 |  |  |  |  | 0 | die "SSL_verify_mode must be a number and not a string"; | 
| 2383 |  |  |  |  |  |  | } | 
| 2384 |  |  |  |  |  |  |  | 
| 2385 | 258 |  |  |  |  | 2005 | my $self = bless {},$class; | 
| 2386 |  |  |  |  |  |  |  | 
| 2387 | 258 |  |  |  |  | 917 | my $vcn_scheme = delete $arg_hash->{SSL_verifycn_scheme}; | 
| 2388 | 258 |  |  |  |  | 607 | my $vcn_publicsuffix = delete $arg_hash->{SSL_verifycn_publicsuffix}; | 
| 2389 | 258 | 50 | 100 |  |  | 2770 | if ( ! $is_server and $verify_mode & 0x01 and | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
| 2390 |  |  |  |  |  |  | ! $vcn_scheme || $vcn_scheme ne 'none' ) { | 
| 2391 |  |  |  |  |  |  |  | 
| 2392 |  |  |  |  |  |  | # gets updated during configure_SSL | 
| 2393 | 90 |  |  |  |  | 207 | my $verify_name; | 
| 2394 | 90 |  |  |  |  | 478 | $self->{verify_name_ref} = \$verify_name; | 
| 2395 |  |  |  |  |  |  |  | 
| 2396 | 90 |  |  |  |  | 241 | my $vcb = $arg_hash->{SSL_verify_callback}; | 
| 2397 |  |  |  |  |  |  | $arg_hash->{SSL_verify_callback} = sub { | 
| 2398 | 201 |  |  | 201 |  | 611 | my ($ok,$ctx_store,$certname,$error,$cert,$depth) = @_; | 
| 2399 | 201 | 100 |  |  |  | 495 | $ok = $vcb->($ok,$ctx_store,$certname,$error,$cert,$depth) if $vcb; | 
| 2400 | 201 | 100 |  |  |  | 5014 | $ok or return 0; | 
| 2401 |  |  |  |  |  |  |  | 
| 2402 | 187 | 100 |  |  |  | 639 | return $ok if $depth != 0; | 
| 2403 |  |  |  |  |  |  |  | 
| 2404 | 90 |  | 33 |  |  | 335 | my $host = $verify_name || ref($vcn_scheme) && $vcn_scheme->{callback} && 'unknown'; | 
| 2405 | 90 | 50 |  |  |  | 258 | if ( ! $host ) { | 
| 2406 | 0 | 0 |  |  |  | 0 | if ( $vcn_scheme ) { | 
| 2407 | 0 |  |  |  |  | 0 | IO::Socket::SSL->_internal_error( | 
| 2408 |  |  |  |  |  |  | "Cannot determine peer hostname for verification",8); | 
| 2409 | 0 |  |  |  |  | 0 | return 0; | 
| 2410 |  |  |  |  |  |  | } | 
| 2411 | 0 |  |  |  |  | 0 | warn "Cannot determine hostname of peer for verification. ". | 
| 2412 |  |  |  |  |  |  | "Disabling default hostname verification for now. ". | 
| 2413 |  |  |  |  |  |  | "Please specify hostname with SSL_verifycn_name and better set SSL_verifycn_scheme too.\n"; | 
| 2414 | 0 |  |  |  |  | 0 | return $ok; | 
| 2415 |  |  |  |  |  |  | } | 
| 2416 |  |  |  |  |  |  |  | 
| 2417 |  |  |  |  |  |  |  | 
| 2418 |  |  |  |  |  |  | # verify name | 
| 2419 | 90 |  |  |  |  | 546 | my $rv = IO::Socket::SSL::verify_hostname_of_cert( | 
| 2420 |  |  |  |  |  |  | $host,$cert,$vcn_scheme,$vcn_publicsuffix ); | 
| 2421 | 90 | 100 |  |  |  | 343 | if ( ! $rv ) { | 
| 2422 | 22 |  |  |  |  | 249 | IO::Socket::SSL->_internal_error( | 
| 2423 |  |  |  |  |  |  | "hostname verification failed",5); | 
| 2424 |  |  |  |  |  |  | } | 
| 2425 | 90 |  |  |  |  | 279 | return $rv; | 
| 2426 | 90 |  |  |  |  | 1311 | }; | 
| 2427 |  |  |  |  |  |  | } | 
| 2428 |  |  |  |  |  |  |  | 
| 2429 | 258 | 100 |  |  |  | 1047 | if ($is_server) { | 
| 2430 | 91 | 50 | 33 |  |  | 739 | if ($arg_hash->{SSL_ticket_keycb} && !$can_tckt_keycb) { | 
| 2431 | 0 |  |  |  |  | 0 | warn "Ticket Key Callback is not supported - ignoring option SSL_ticket_keycb\n"; | 
| 2432 | 0 |  |  |  |  | 0 | delete $arg_hash->{SSL_ticket_keycb}; | 
| 2433 |  |  |  |  |  |  | } | 
| 2434 |  |  |  |  |  |  | } | 
| 2435 |  |  |  |  |  |  |  | 
| 2436 |  |  |  |  |  |  |  | 
| 2437 | 258 |  |  |  |  | 737 | my $ssl_op = $DEFAULT_SSL_OP; | 
| 2438 |  |  |  |  |  |  |  | 
| 2439 | 258 |  |  |  |  | 546 | my $ver; | 
| 2440 | 258 |  |  |  |  | 6149 | for (split(/\s*:\s*/,$arg_hash->{SSL_version})) { | 
| 2441 | 1180 | 50 |  |  |  | 8083 | m{^(!?)(?:(SSL(?:v2|v3|v23|v2/3))|(TLSv1(?:_?[123])?))$}i | 
| 2442 |  |  |  |  |  |  | or croak("invalid SSL_version specified"); | 
| 2443 | 1180 |  |  |  |  | 4393 | my $not = $1; | 
| 2444 | 1180 |  | 66 |  |  | 12271 | ( my $v = lc($2||$3) ) =~s{^(...)}{\U$1}; | 
| 2445 | 1180 | 100 |  |  |  | 3267 | if ( $not ) { | 
| 2446 | 922 |  |  |  |  | 3335 | $ssl_op |= $SSL_OP_NO{$v}; | 
| 2447 |  |  |  |  |  |  | } else { | 
| 2448 | 258 | 50 | 33 |  |  | 1089 | croak("cannot set multiple SSL protocols in SSL_version") | 
| 2449 |  |  |  |  |  |  | if $ver && $v ne $ver; | 
| 2450 | 258 |  |  |  |  | 667 | $ver = $v; | 
| 2451 | 258 |  |  |  |  | 854 | $ver =~s{/}{}; # interpret SSLv2/3 as SSLv23 | 
| 2452 | 258 |  |  |  |  | 1437 | $ver =~s{(TLSv1)(\d)}{$1\_$2}; # TLSv1_1 | 
| 2453 |  |  |  |  |  |  | } | 
| 2454 |  |  |  |  |  |  | } | 
| 2455 |  |  |  |  |  |  |  | 
| 2456 | 258 | 100 |  |  |  | 6553 | my $ctx_new_sub = | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 2457 |  |  |  |  |  |  | $ver eq 'TLSv1_3' ? $CTX_tlsv1_3_new : | 
| 2458 |  |  |  |  |  |  | UNIVERSAL::can( 'Net::SSLeay', | 
| 2459 |  |  |  |  |  |  | $ver eq 'SSLv2'   ? 'CTX_v2_new' : | 
| 2460 |  |  |  |  |  |  | $ver eq 'SSLv3'   ? 'CTX_v3_new' : | 
| 2461 |  |  |  |  |  |  | $ver eq 'TLSv1'   ? 'CTX_tlsv1_new' : | 
| 2462 |  |  |  |  |  |  | $ver eq 'TLSv1_1' ? 'CTX_tlsv1_1_new' : | 
| 2463 |  |  |  |  |  |  | $ver eq 'TLSv1_2' ? 'CTX_tlsv1_2_new' : | 
| 2464 |  |  |  |  |  |  | 'CTX_new' | 
| 2465 |  |  |  |  |  |  | ) | 
| 2466 |  |  |  |  |  |  | or return IO::Socket::SSL->_internal_error("SSL Version $ver not supported",9); | 
| 2467 |  |  |  |  |  |  |  | 
| 2468 |  |  |  |  |  |  | # For SNI in server mode we need a separate context for each certificate. | 
| 2469 | 256 |  |  |  |  | 1149 | my %ctx; | 
| 2470 | 256 | 100 |  |  |  | 1028 | if ($is_server) { | 
| 2471 | 91 |  |  |  |  | 356 | my %sni; | 
| 2472 | 91 |  |  |  |  | 435 | for my $opt (qw(SSL_key SSL_key_file SSL_cert SSL_cert_file)) { | 
| 2473 | 364 | 100 |  |  |  | 1480 | my $val  = $arg_hash->{$opt} or next; | 
| 2474 | 177 | 100 |  |  |  | 929 | if ( ref($val) eq 'HASH' ) { | 
| 2475 | 12 |  |  |  |  | 78 | while ( my ($host,$v) = each %$val ) { | 
| 2476 | 44 |  |  |  |  | 178 | $sni{lc($host)}{$opt} = $v; | 
| 2477 |  |  |  |  |  |  | } | 
| 2478 |  |  |  |  |  |  | } | 
| 2479 |  |  |  |  |  |  | } | 
| 2480 | 91 |  |  |  |  | 1067 | while (my ($host,$v) = each %sni) { | 
| 2481 | 22 | 100 |  |  |  | 312 | $ctx{$host} = $host =~m{%} ? $v : { %$arg_hash, %$v }; | 
| 2482 |  |  |  |  |  |  | } | 
| 2483 |  |  |  |  |  |  | } | 
| 2484 | 256 | 100 |  |  |  | 1820 | $ctx{''} = $arg_hash if ! %ctx; | 
| 2485 |  |  |  |  |  |  |  | 
| 2486 | 256 |  |  |  |  | 2182 | for my $host (sort keys %ctx) { | 
| 2487 | 272 |  |  |  |  | 894 | my $arg_hash = delete $ctx{$host}; | 
| 2488 | 272 |  |  |  |  | 852 | my $ctx; | 
| 2489 | 272 | 100 |  |  |  | 1088 | if ($host =~m{^([^%]*)%}) { | 
| 2490 | 2 | 50 |  |  |  | 12 | $ctx = $ctx{$1} or return IO::Socket::SSL->error( | 
| 2491 |  |  |  |  |  |  | "SSL Context init for $host failed - no config for $1"); | 
| 2492 | 2 | 50 |  |  |  | 10 | if (my @k = grep { !m{^SSL_(?:cert|key)(?:_file)?$} } | 
|  | 4 |  |  |  |  | 28 |  | 
| 2493 |  |  |  |  |  |  | keys %$arg_hash) { | 
| 2494 | 0 |  |  |  |  | 0 | return IO::Socket::SSL->error( | 
| 2495 |  |  |  |  |  |  | "invalid keys @k in configuration '$host' of additional certs"); | 
| 2496 |  |  |  |  |  |  | } | 
| 2497 | 2 | 50 |  |  |  | 6 | $can_multi_cert or return IO::Socket::SSL->error( | 
| 2498 |  |  |  |  |  |  | "no support for both RSA and ECC certificate in same context"); | 
| 2499 | 2 |  |  |  |  | 6 | $host = $1; | 
| 2500 | 2 |  |  |  |  | 34 | goto just_configure_certs; | 
| 2501 |  |  |  |  |  |  | } | 
| 2502 |  |  |  |  |  |  |  | 
| 2503 | 270 | 50 |  |  |  | 46486 | $ctx = $ctx_new_sub->() or return | 
| 2504 |  |  |  |  |  |  | IO::Socket::SSL->error("SSL Context init failed"); | 
| 2505 | 270 | 50 |  |  |  | 1365 | $CTX_CREATED_IN_THIS_THREAD{$ctx} = 1 if $use_threads; | 
| 2506 | 270 |  |  |  |  | 771 | $ctx{$host} = $ctx; # replace value in %ctx with real context | 
| 2507 |  |  |  |  |  |  |  | 
| 2508 |  |  |  |  |  |  | # SSL_OP_CIPHER_SERVER_PREFERENCE | 
| 2509 | 270 | 100 |  |  |  | 1254 | $ssl_op |= 0x00400000 if $arg_hash->{SSL_honor_cipher_order}; | 
| 2510 |  |  |  |  |  |  |  | 
| 2511 | 270 | 100 | 100 |  |  | 3113 | if ($ver eq 'SSLv23' && !($ssl_op & $SSL_OP_NO{SSLv3})) { | 
| 2512 |  |  |  |  |  |  | # At least LibreSSL disables SSLv3 by default in SSL_CTX_new. | 
| 2513 |  |  |  |  |  |  | # If we really want SSL3.0 we need to explicitly allow it with | 
| 2514 |  |  |  |  |  |  | # SSL_CTX_clear_options. | 
| 2515 | 21 |  |  |  |  | 141 | Net::SSLeay::CTX_clear_options($ctx,$SSL_OP_NO{SSLv3}); | 
| 2516 |  |  |  |  |  |  | } | 
| 2517 |  |  |  |  |  |  |  | 
| 2518 | 270 |  |  |  |  | 2048 | Net::SSLeay::CTX_set_options($ctx,$ssl_op); | 
| 2519 |  |  |  |  |  |  |  | 
| 2520 |  |  |  |  |  |  | # enable X509_V_FLAG_PARTIAL_CHAIN if possible (OpenSSL 1.1.0+) | 
| 2521 | 270 | 50 |  |  |  | 863 | $check_partial_chain && $check_partial_chain->($ctx); | 
| 2522 |  |  |  |  |  |  |  | 
| 2523 |  |  |  |  |  |  | # if we don't set session_id_context if client certificate is expected | 
| 2524 |  |  |  |  |  |  | # client session caching will fail | 
| 2525 |  |  |  |  |  |  | # if user does not provide explicit id just use the stringification | 
| 2526 |  |  |  |  |  |  | # of the context | 
| 2527 | 270 | 100 | 66 |  |  | 2647 | if($arg_hash->{SSL_server} and my $id = | 
|  |  |  | 100 |  |  |  |  | 
| 2528 |  |  |  |  |  |  | $arg_hash->{SSL_session_id_context} || | 
| 2529 |  |  |  |  |  |  | ( $arg_hash->{SSL_verify_mode} & 0x01 ) && "$ctx" ) { | 
| 2530 | 9 |  |  |  |  | 39 | Net::SSLeay::CTX_set_session_id_context($ctx,$id,length($id)); | 
| 2531 |  |  |  |  |  |  | } | 
| 2532 |  |  |  |  |  |  |  | 
| 2533 |  |  |  |  |  |  | # SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER makes syswrite return if at least one | 
| 2534 |  |  |  |  |  |  | # buffer was written and not block for the rest | 
| 2535 |  |  |  |  |  |  | # SSL_MODE_ENABLE_PARTIAL_WRITE can be necessary for non-blocking because we | 
| 2536 |  |  |  |  |  |  | # cannot guarantee, that the location of the buffer stays constant | 
| 2537 |  |  |  |  |  |  | Net::SSLeay::CTX_set_mode( $ctx, | 
| 2538 |  |  |  |  |  |  | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | | 
| 2539 |  |  |  |  |  |  | SSL_MODE_ENABLE_PARTIAL_WRITE | | 
| 2540 | 270 | 50 |  |  |  | 2427 | ($arg_hash->{SSL_mode_release_buffers} ? $ssl_mode_release_buffers : 0) | 
| 2541 |  |  |  |  |  |  | ); | 
| 2542 |  |  |  |  |  |  |  | 
| 2543 | 270 | 100 |  |  |  | 1714 | if ( my $proto_list = $arg_hash->{SSL_npn_protocols} ) { | 
| 2544 | 3 | 50 |  |  |  | 13 | return IO::Socket::SSL->_internal_error("NPN not supported in Net::SSLeay",9) | 
| 2545 |  |  |  |  |  |  | if ! $can_npn; | 
| 2546 | 3 | 100 |  |  |  | 32 | if($arg_hash->{SSL_server}) { | 
| 2547 |  |  |  |  |  |  | # on server side SSL_npn_protocols means a list of advertised protocols | 
| 2548 | 2 |  |  |  |  | 30 | Net::SSLeay::CTX_set_next_protos_advertised_cb($ctx, $proto_list); | 
| 2549 |  |  |  |  |  |  | } else { | 
| 2550 |  |  |  |  |  |  | # on client side SSL_npn_protocols means a list of preferred protocols | 
| 2551 |  |  |  |  |  |  | # negotiation algorithm used is "as-openssl-implements-it" | 
| 2552 | 1 |  |  |  |  | 89 | Net::SSLeay::CTX_set_next_proto_select_cb($ctx, $proto_list); | 
| 2553 |  |  |  |  |  |  | } | 
| 2554 |  |  |  |  |  |  | } | 
| 2555 |  |  |  |  |  |  |  | 
| 2556 | 270 | 100 |  |  |  | 956 | if ( my $proto_list = $arg_hash->{SSL_alpn_protocols} ) { | 
| 2557 | 3 | 50 |  |  |  | 51 | return IO::Socket::SSL->_internal_error("ALPN not supported in Net::SSLeay",9) | 
| 2558 |  |  |  |  |  |  | if ! $can_alpn; | 
| 2559 | 3 | 100 |  |  |  | 109 | if($arg_hash->{SSL_server}) { | 
| 2560 | 2 |  |  |  |  | 26 | Net::SSLeay::CTX_set_alpn_select_cb($ctx, $proto_list); | 
| 2561 |  |  |  |  |  |  | } else { | 
| 2562 | 1 |  |  |  |  | 78 | Net::SSLeay::CTX_set_alpn_protos($ctx, $proto_list); | 
| 2563 |  |  |  |  |  |  | } | 
| 2564 |  |  |  |  |  |  | } | 
| 2565 |  |  |  |  |  |  |  | 
| 2566 | 270 | 50 |  |  |  | 925 | if ($arg_hash->{SSL_ticket_keycb}) { | 
| 2567 | 0 |  |  |  |  | 0 | my $cb = $arg_hash->{SSL_ticket_keycb}; | 
| 2568 | 0 | 0 |  |  |  | 0 | ($cb,my $arg) = ref($cb) eq 'CODE' ? ($cb):@$cb; | 
| 2569 | 0 |  |  |  |  | 0 | Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb($ctx,$cb,$arg); | 
| 2570 |  |  |  |  |  |  | } | 
| 2571 |  |  |  |  |  |  |  | 
| 2572 |  |  |  |  |  |  | # Try to apply SSL_ca even if SSL_verify_mode is 0, so that they can be | 
| 2573 |  |  |  |  |  |  | # used to verify OCSP responses. | 
| 2574 |  |  |  |  |  |  | # If applying fails complain only if verify_mode != VERIFY_NONE. | 
| 2575 | 270 | 100 | 100 |  |  | 4743 | if ( $arg_hash->{SSL_ca} | 
|  |  | 50 | 66 |  |  |  |  | 
| 2576 |  |  |  |  |  |  | || defined $arg_hash->{SSL_ca_file} | 
| 2577 |  |  |  |  |  |  | || defined $arg_hash->{SSL_ca_path} ) { | 
| 2578 | 107 |  |  |  |  | 737 | my $file = $arg_hash->{SSL_ca_file}; | 
| 2579 | 107 | 50 | 33 |  |  | 532 | $file = undef if ref($file) eq 'SCALAR' && ! $$file; | 
| 2580 | 107 |  |  |  |  | 328 | my $dir = $arg_hash->{SSL_ca_path}; | 
| 2581 | 107 | 50 | 33 |  |  | 477 | $dir = undef if ref($dir) eq 'SCALAR' && ! $$dir; | 
| 2582 | 107 | 100 |  |  |  | 356 | if ( $arg_hash->{SSL_ca} ) { | 
| 2583 | 32 |  |  |  |  | 109 | my $store = Net::SSLeay::CTX_get_cert_store($ctx); | 
| 2584 | 32 |  |  |  |  | 46 | for (@{$arg_hash->{SSL_ca}}) { | 
|  | 32 |  |  |  |  | 156 |  | 
| 2585 | 33 | 50 |  |  |  | 154 | Net::SSLeay::X509_STORE_add_cert($store,$_) or | 
| 2586 |  |  |  |  |  |  | return IO::Socket::SSL->error( | 
| 2587 |  |  |  |  |  |  | "Failed to add certificate to CA store"); | 
| 2588 |  |  |  |  |  |  | } | 
| 2589 |  |  |  |  |  |  | } | 
| 2590 | 107 | 50 |  |  |  | 369 | $dir = join($OPENSSL_LIST_SEPARATOR,@$dir) if ref($dir); | 
| 2591 | 107 | 50 | 66 |  |  | 12798 | if ( $file || $dir and ! Net::SSLeay::CTX_load_verify_locations( | 
|  |  |  | 50 |  |  |  |  | 
|  |  |  | 50 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 2592 |  |  |  |  |  |  | $ctx, $file || '', $dir || '')) { | 
| 2593 | 0 | 0 |  |  |  | 0 | return IO::Socket::SSL->error( | 
| 2594 |  |  |  |  |  |  | "Invalid certificate authority locations") | 
| 2595 |  |  |  |  |  |  | if $verify_mode != $Net_SSLeay_VERIFY_NONE; | 
| 2596 |  |  |  |  |  |  | } | 
| 2597 |  |  |  |  |  |  | } elsif ( my %ca = IO::Socket::SSL::default_ca()) { | 
| 2598 |  |  |  |  |  |  | # no CA path given, continue with system defaults | 
| 2599 | 163 |  |  |  |  | 760 | my $dir = $ca{SSL_ca_path}; | 
| 2600 | 163 | 50 |  |  |  | 826 | $dir = join($OPENSSL_LIST_SEPARATOR,@$dir) if ref($dir); | 
| 2601 | 163 | 50 | 100 |  |  | 5420 | if (! Net::SSLeay::CTX_load_verify_locations( $ctx, | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 2602 |  |  |  |  |  |  | $ca{SSL_ca_file} || '',$dir || '') | 
| 2603 |  |  |  |  |  |  | && $verify_mode != $Net_SSLeay_VERIFY_NONE) { | 
| 2604 | 0 |  |  |  |  | 0 | return IO::Socket::SSL->error( | 
| 2605 |  |  |  |  |  |  | "Invalid default certificate authority locations") | 
| 2606 |  |  |  |  |  |  | } | 
| 2607 |  |  |  |  |  |  | } | 
| 2608 |  |  |  |  |  |  |  | 
| 2609 | 270 | 100 | 100 |  |  | 2605 | if ($is_server && ($verify_mode & $Net_SSLeay_VERIFY_PEER)) { | 
| 2610 | 9 | 50 |  |  |  | 32 | if ($arg_hash->{SSL_client_ca}) { | 
| 2611 | 0 |  |  |  |  | 0 | for (@{$arg_hash->{SSL_client_ca}}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 2612 | 0 | 0 |  |  |  | 0 | return IO::Socket::SSL->error( | 
| 2613 |  |  |  |  |  |  | "Failed to add certificate to client CA list") if | 
| 2614 |  |  |  |  |  |  | ! Net::SSLeay::CTX_add_client_CA($ctx,$_); | 
| 2615 |  |  |  |  |  |  | } | 
| 2616 |  |  |  |  |  |  | } | 
| 2617 | 9 | 50 |  |  |  | 22 | if ($arg_hash->{SSL_client_ca_file}) { | 
| 2618 |  |  |  |  |  |  | my $list = Net::SSLeay::load_client_CA_file( | 
| 2619 | 0 | 0 |  |  |  | 0 | $arg_hash->{SSL_client_ca_file}) or | 
| 2620 |  |  |  |  |  |  | return IO::Socket::SSL->error( | 
| 2621 |  |  |  |  |  |  | "Failed to load certificate to client CA list"); | 
| 2622 | 0 |  |  |  |  | 0 | Net::SSLeay::CTX_set_client_CA_list($ctx,$list); | 
| 2623 |  |  |  |  |  |  | } | 
| 2624 |  |  |  |  |  |  | } | 
| 2625 |  |  |  |  |  |  |  | 
| 2626 | 270 |  |  |  |  | 799 | my $X509_STORE_flags = $DEFAULT_X509_STORE_flags; | 
| 2627 | 270 | 50 |  |  |  | 894 | if ($arg_hash->{'SSL_check_crl'}) { | 
| 2628 | 0 |  |  |  |  | 0 | $X509_STORE_flags |= Net::SSLeay::X509_V_FLAG_CRL_CHECK(); | 
| 2629 | 0 | 0 |  |  |  | 0 | if ($arg_hash->{'SSL_crl_file'}) { | 
| 2630 | 0 |  |  |  |  | 0 | my $bio = Net::SSLeay::BIO_new_file($arg_hash->{'SSL_crl_file'}, 'r'); | 
| 2631 | 0 |  |  |  |  | 0 | my $crl = Net::SSLeay::PEM_read_bio_X509_CRL($bio); | 
| 2632 | 0 |  |  |  |  | 0 | Net::SSLeay::BIO_free($bio); | 
| 2633 | 0 | 0 |  |  |  | 0 | if ( $crl ) { | 
| 2634 | 0 |  |  |  |  | 0 | Net::SSLeay::X509_STORE_add_crl(Net::SSLeay::CTX_get_cert_store($ctx), $crl); | 
| 2635 | 0 |  |  |  |  | 0 | Net::SSLeay::X509_CRL_free($crl); | 
| 2636 |  |  |  |  |  |  | } else { | 
| 2637 | 0 |  |  |  |  | 0 | return IO::Socket::SSL->error("Invalid certificate revocation list"); | 
| 2638 |  |  |  |  |  |  | } | 
| 2639 |  |  |  |  |  |  | } | 
| 2640 |  |  |  |  |  |  | } | 
| 2641 |  |  |  |  |  |  |  | 
| 2642 |  |  |  |  |  |  | Net::SSLeay::X509_STORE_set_flags( | 
| 2643 | 270 | 50 |  |  |  | 2700 | Net::SSLeay::CTX_get_cert_store($ctx), | 
| 2644 |  |  |  |  |  |  | $X509_STORE_flags | 
| 2645 |  |  |  |  |  |  | ) if $X509_STORE_flags; | 
| 2646 |  |  |  |  |  |  |  | 
| 2647 |  |  |  |  |  |  | Net::SSLeay::CTX_set_default_passwd_cb($ctx,$arg_hash->{SSL_passwd_cb}) | 
| 2648 | 270 | 100 |  |  |  | 1164 | if $arg_hash->{SSL_passwd_cb}; | 
| 2649 |  |  |  |  |  |  |  | 
| 2650 | 272 |  |  |  |  | 744 | just_configure_certs: | 
| 2651 |  |  |  |  |  |  | my ($havekey,$havecert); | 
| 2652 | 272 | 100 |  |  |  | 1823 | if ( my $x509 = $arg_hash->{SSL_cert} ) { | 
|  |  | 100 |  |  |  |  |  | 
| 2653 |  |  |  |  |  |  | # binary, e.g. X509* | 
| 2654 |  |  |  |  |  |  | # we have either a single certificate or a list with | 
| 2655 |  |  |  |  |  |  | # a chain of certificates | 
| 2656 | 31 | 100 |  |  |  | 137 | my @x509 = ref($x509) eq 'ARRAY' ? @$x509: ($x509); | 
| 2657 | 31 |  |  |  |  | 71 | my $cert = shift @x509; | 
| 2658 | 31 | 50 |  |  |  | 381 | Net::SSLeay::CTX_use_certificate( $ctx,$cert ) | 
| 2659 |  |  |  |  |  |  | || return IO::Socket::SSL->error("Failed to use Certificate"); | 
| 2660 | 31 |  |  |  |  | 98 | foreach my $ca (@x509) { | 
| 2661 | 1 | 50 |  |  |  | 6 | Net::SSLeay::CTX_add_extra_chain_cert( $ctx,$ca ) | 
| 2662 |  |  |  |  |  |  | || return IO::Socket::SSL->error("Failed to use Certificate"); | 
| 2663 |  |  |  |  |  |  | } | 
| 2664 | 31 |  |  |  |  | 96 | $havecert = 'OBJ'; | 
| 2665 |  |  |  |  |  |  | } elsif ( my $f = $arg_hash->{SSL_cert_file} ) { | 
| 2666 |  |  |  |  |  |  | # try to load chain from PEM or certificate from ASN1 | 
| 2667 | 82 |  |  |  |  | 280 | my @err; | 
| 2668 | 82 | 100 |  |  |  | 13173 | if (Net::SSLeay::CTX_use_certificate_chain_file($ctx,$f)) { | 
|  |  | 100 |  |  |  |  |  | 
| 2669 | 79 |  |  |  |  | 648 | $havecert = 'PEM'; | 
| 2670 |  |  |  |  |  |  | } elsif (do { | 
| 2671 | 3 |  |  |  |  | 116 | push @err, [ PEM => _errstack() ]; | 
| 2672 | 3 |  |  |  |  | 466 | Net::SSLeay::CTX_use_certificate_file($ctx,$f,FILETYPE_ASN1) | 
| 2673 |  |  |  |  |  |  | }) { | 
| 2674 | 1 |  |  |  |  | 15 | $havecert = 'DER'; | 
| 2675 |  |  |  |  |  |  | } else { | 
| 2676 | 2 |  |  |  |  | 17 | push @err, [ DER => _errstack() ]; | 
| 2677 |  |  |  |  |  |  | # try to load certificate, key and chain from PKCS12 file | 
| 2678 | 2 |  |  |  |  | 8380 | my ($key,$cert,@chain) = Net::SSLeay::P_PKCS12_load_file($f,1); | 
| 2679 | 2 | 50 | 66 |  |  | 59 | if (!$cert and $arg_hash->{SSL_passwd_cb} | 
|  |  |  | 33 |  |  |  |  | 
| 2680 |  |  |  |  |  |  | and defined( my $pw = $arg_hash->{SSL_passwd_cb}->(0))) { | 
| 2681 | 1 |  |  |  |  | 4918 | ($key,$cert,@chain) = Net::SSLeay::P_PKCS12_load_file($f,1,$pw); | 
| 2682 |  |  |  |  |  |  | } | 
| 2683 | 2 |  |  |  |  | 13 | PKCS12: while ($cert) { | 
| 2684 | 2 | 50 |  |  |  | 20 | Net::SSLeay::CTX_use_certificate($ctx,$cert) or last; | 
| 2685 |  |  |  |  |  |  | # Net::SSLeay::P_PKCS12_load_file is implemented using | 
| 2686 |  |  |  |  |  |  | # OpenSSL PKCS12_parse which according to the source code | 
| 2687 |  |  |  |  |  |  | # returns the chain with the last CA certificate first (i.e. | 
| 2688 |  |  |  |  |  |  | # reverse order as in the PKCS12 file). This is not | 
| 2689 |  |  |  |  |  |  | # documented but given the age of this function we'll assume | 
| 2690 |  |  |  |  |  |  | # that this will stay this way in the future. | 
| 2691 | 2 |  |  |  |  | 12 | while (my $ca = pop @chain) { | 
| 2692 | 0 | 0 |  |  |  | 0 | Net::SSLeay::CTX_add_extra_chain_cert($ctx,$ca) | 
| 2693 |  |  |  |  |  |  | or last PKCS12; | 
| 2694 |  |  |  |  |  |  | } | 
| 2695 | 2 | 50 | 33 |  |  | 44 | last if $key && ! Net::SSLeay::CTX_use_PrivateKey($ctx,$key); | 
| 2696 | 2 |  |  |  |  | 15 | $havecert = 'PKCS12'; | 
| 2697 | 2 |  |  |  |  | 13 | last; | 
| 2698 |  |  |  |  |  |  | } | 
| 2699 | 2 | 50 |  |  |  | 25 | $havekey = 'PKCS12' if $key; | 
| 2700 | 2 | 50 |  |  |  | 24 | Net::SSLeay::X509_free($cert) if $cert; | 
| 2701 | 2 | 50 |  |  |  | 13 | Net::SSLeay::EVP_PKEY_free($key) if $key; | 
| 2702 |  |  |  |  |  |  | # don't free @chain, because CTX_add_extra_chain_cert | 
| 2703 |  |  |  |  |  |  | # did not duplicate the certificates | 
| 2704 |  |  |  |  |  |  | } | 
| 2705 | 82 | 50 |  |  |  | 733 | if (!$havecert) { | 
| 2706 | 0 |  |  |  |  | 0 | push @err, [ PKCS12 => _errstack() ]; | 
| 2707 | 0 |  |  |  |  | 0 | my $err = "Failed to load certificate from file $f:"; | 
| 2708 | 0 |  |  |  |  | 0 | for(@err) { | 
| 2709 | 0 |  |  |  |  | 0 | my ($type,@e) = @$_; | 
| 2710 | 0 | 0 |  |  |  | 0 | $err .= " [format:$type] @e **" if @e; | 
| 2711 |  |  |  |  |  |  | } | 
| 2712 | 0 |  |  |  |  | 0 | return IO::Socket::SSL->error($err); | 
| 2713 |  |  |  |  |  |  | } | 
| 2714 |  |  |  |  |  |  | } | 
| 2715 |  |  |  |  |  |  |  | 
| 2716 | 272 | 100 | 100 |  |  | 3107 | if (!$havecert || $havekey) { | 
|  |  | 100 | 66 |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 2717 |  |  |  |  |  |  | # skip SSL_key_* | 
| 2718 |  |  |  |  |  |  | } elsif ( my $pkey = $arg_hash->{SSL_key} ) { | 
| 2719 |  |  |  |  |  |  | # binary, e.g. EVP_PKEY* | 
| 2720 | 28 | 50 |  |  |  | 193 | Net::SSLeay::CTX_use_PrivateKey($ctx, $pkey) | 
| 2721 |  |  |  |  |  |  | || return IO::Socket::SSL->error("Failed to use Private Key"); | 
| 2722 | 28 |  |  |  |  | 68 | $havekey = 'MEM'; | 
| 2723 |  |  |  |  |  |  | } elsif ( my $f = $arg_hash->{SSL_key_file} | 
| 2724 |  |  |  |  |  |  | || (($havecert eq 'PEM') ? $arg_hash->{SSL_cert_file}:undef) ) { | 
| 2725 | 83 |  |  |  |  | 472 | for my $ft ( FILETYPE_PEM, FILETYPE_ASN1 ) { | 
| 2726 | 84 | 100 |  |  |  | 8649 | if (Net::SSLeay::CTX_use_PrivateKey_file($ctx,$f,$ft)) { | 
| 2727 | 83 | 100 |  |  |  | 766 | $havekey = ($ft == FILETYPE_PEM) ? 'PEM':'DER'; | 
| 2728 | 83 |  |  |  |  | 292 | last; | 
| 2729 |  |  |  |  |  |  | } | 
| 2730 |  |  |  |  |  |  | } | 
| 2731 | 83 | 50 |  |  |  | 383 | $havekey or return IO::Socket::SSL->error( | 
| 2732 |  |  |  |  |  |  | "Failed to load key from file (no PEM or DER)"); | 
| 2733 |  |  |  |  |  |  | } | 
| 2734 |  |  |  |  |  |  |  | 
| 2735 | 272 | 0 | 66 |  |  | 2996 | Net::SSLeay::CTX_set_post_handshake_auth($ctx,1) | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 2736 |  |  |  |  |  |  | if (!$is_server && $can_pha && $havecert && $havekey); | 
| 2737 |  |  |  |  |  |  | } | 
| 2738 |  |  |  |  |  |  |  | 
| 2739 | 256 | 100 |  |  |  | 1116 | if ($arg_hash->{SSL_server}) { | 
| 2740 |  |  |  |  |  |  |  | 
| 2741 | 91 | 50 |  |  |  | 660 | if ( my $f = $arg_hash->{SSL_dh_file} ) { | 
|  |  | 50 |  |  |  |  |  | 
| 2742 | 0 |  | 0 |  |  | 0 | my $bio = Net::SSLeay::BIO_new_file( $f,'r' ) | 
| 2743 |  |  |  |  |  |  | || return IO::Socket::SSL->error( "Failed to open DH file $f" ); | 
| 2744 | 0 |  |  |  |  | 0 | my $dh = Net::SSLeay::PEM_read_bio_DHparams($bio); | 
| 2745 | 0 |  |  |  |  | 0 | Net::SSLeay::BIO_free($bio); | 
| 2746 | 0 | 0 |  |  |  | 0 | $dh || return IO::Socket::SSL->error( "Failed to read PEM for DH from $f - wrong format?" ); | 
| 2747 | 0 |  |  |  |  | 0 | my $rv; | 
| 2748 | 0 |  |  |  |  | 0 | for (values (%ctx)) { | 
| 2749 | 0 | 0 |  |  |  | 0 | $rv = Net::SSLeay::CTX_set_tmp_dh( $_,$dh ) or last; | 
| 2750 |  |  |  |  |  |  | } | 
| 2751 | 0 |  |  |  |  | 0 | Net::SSLeay::DH_free( $dh ); | 
| 2752 | 0 | 0 |  |  |  | 0 | $rv || return IO::Socket::SSL->error( "Failed to set DH from $f" ); | 
| 2753 |  |  |  |  |  |  | } elsif ( my $dh = $arg_hash->{SSL_dh} ) { | 
| 2754 |  |  |  |  |  |  | # binary, e.g. DH* | 
| 2755 |  |  |  |  |  |  |  | 
| 2756 | 91 |  |  |  |  | 333 | for( values %ctx ) { | 
| 2757 | 105 | 50 |  |  |  | 1129 | Net::SSLeay::CTX_set_tmp_dh( $_,$dh ) || return | 
| 2758 |  |  |  |  |  |  | IO::Socket::SSL->error( "Failed to set DH from SSL_dh" ); | 
| 2759 |  |  |  |  |  |  | } | 
| 2760 |  |  |  |  |  |  | } | 
| 2761 |  |  |  |  |  |  | } | 
| 2762 |  |  |  |  |  |  |  | 
| 2763 | 256 | 100 |  |  |  | 1696 | if ( my $curve = $arg_hash->{SSL_ecdh_curve} ) { | 
| 2764 | 91 | 50 |  |  |  | 320 | return IO::Socket::SSL->_internal_error( | 
| 2765 |  |  |  |  |  |  | "ECDH curve needs Net::SSLeay>=1.56 and OpenSSL>=1.0",9) | 
| 2766 |  |  |  |  |  |  | if ! $can_ecdh; | 
| 2767 |  |  |  |  |  |  |  | 
| 2768 | 91 |  |  |  |  | 290 | for(values %ctx) { | 
| 2769 | 105 | 50 | 33 |  |  | 1997 | if ($arg_hash->{SSL_server} and $curve eq 'auto') { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 2770 | 0 | 0 |  |  |  | 0 | if ($can_ecdh eq 'can_auto') { | 
|  |  | 0 |  |  |  |  |  | 
| 2771 | 0 | 0 |  |  |  | 0 | Net::SSLeay::CTX_set_ecdh_auto($_,1) or | 
| 2772 |  |  |  |  |  |  | return IO::Socket::SSL->error( | 
| 2773 |  |  |  |  |  |  | "failed to set ECDH curve context"); | 
| 2774 |  |  |  |  |  |  | } elsif ($can_ecdh eq 'auto') { | 
| 2775 |  |  |  |  |  |  | # automatically enabled anyway | 
| 2776 |  |  |  |  |  |  | } else { | 
| 2777 | 0 |  |  |  |  | 0 | return IO::Socket::SSL->error( | 
| 2778 |  |  |  |  |  |  | "SSL_CTX_set_ecdh_auto not implemented"); | 
| 2779 |  |  |  |  |  |  | } | 
| 2780 |  |  |  |  |  |  |  | 
| 2781 |  |  |  |  |  |  | } elsif ($set_groups_list) { | 
| 2782 | 0 | 0 |  |  |  | 0 | $set_groups_list->($_,$curve) or return IO::Socket::SSL->error( | 
| 2783 |  |  |  |  |  |  | "failed to set ECDH groups/curves on context"); | 
| 2784 |  |  |  |  |  |  | # needed for OpenSSL 1.0.2 if ($can_ecdh eq 'can_auto') { | 
| 2785 | 0 | 0 |  |  |  | 0 | Net::SSLeay::CTX_set_ecdh_auto($_,1) if $can_ecdh eq 'can_auto'; | 
| 2786 |  |  |  |  |  |  | } elsif ($curve =~m{:}) { | 
| 2787 | 0 |  |  |  |  | 0 | return IO::Socket::SSL->error( | 
| 2788 |  |  |  |  |  |  | "SSL_CTX_groups_list or SSL_CTX_curves_list not implemented"); | 
| 2789 |  |  |  |  |  |  |  | 
| 2790 |  |  |  |  |  |  | } elsif ($arg_hash->{SSL_server}) { | 
| 2791 | 105 | 100 |  |  |  | 955 | if ( $curve !~ /^\d+$/ ) { | 
| 2792 |  |  |  |  |  |  | # name of curve, find NID | 
| 2793 | 91 |  | 50 |  |  | 1070 | $curve = Net::SSLeay::OBJ_txt2nid($curve) | 
| 2794 |  |  |  |  |  |  | || return IO::Socket::SSL->error( | 
| 2795 |  |  |  |  |  |  | "cannot find NID for curve name '$curve'"); | 
| 2796 |  |  |  |  |  |  | } | 
| 2797 | 105 | 50 |  |  |  | 6492 | my $ecdh = Net::SSLeay::EC_KEY_new_by_curve_name($curve) or | 
| 2798 |  |  |  |  |  |  | return IO::Socket::SSL->error( | 
| 2799 |  |  |  |  |  |  | "cannot create curve for NID $curve"); | 
| 2800 | 105 |  |  |  |  | 485 | for( values %ctx ) { | 
| 2801 | 157 | 50 |  |  |  | 1323 | Net::SSLeay::CTX_set_tmp_ecdh($_,$ecdh) or | 
| 2802 |  |  |  |  |  |  | return IO::Socket::SSL->error( | 
| 2803 |  |  |  |  |  |  | "failed to set ECDH curve context"); | 
| 2804 |  |  |  |  |  |  | } | 
| 2805 | 105 |  |  |  |  | 562 | Net::SSLeay::EC_KEY_free($ecdh); | 
| 2806 |  |  |  |  |  |  | } | 
| 2807 |  |  |  |  |  |  | } | 
| 2808 |  |  |  |  |  |  | } | 
| 2809 |  |  |  |  |  |  |  | 
| 2810 | 256 |  |  |  |  | 850 | my $verify_cb = $arg_hash->{SSL_verify_callback}; | 
| 2811 | 256 |  |  |  |  | 585 | my @accept_fp; | 
| 2812 | 256 | 100 |  |  |  | 920 | if ( my $fp = $arg_hash->{SSL_fingerprint} ) { | 
| 2813 | 9 | 100 |  |  |  | 26 | for( ref($fp) ? @$fp : $fp) { | 
| 2814 | 11 | 50 |  |  |  | 105 | my ($algo,$pubkey,$digest) = m{^(?:([\w-]+)\$)?(pub\$)?([a-f\d:]+)$}i | 
| 2815 |  |  |  |  |  |  | or return IO::Socket::SSL->_internal_error("invalid fingerprint '$_'",9); | 
| 2816 | 11 |  |  |  |  | 89 | ( $digest = lc($digest) ) =~s{:}{}g; | 
| 2817 | 11 | 0 | 33 |  |  | 30 | $algo ||= | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 2818 |  |  |  |  |  |  | length($digest) == 32 ? 'md5' : | 
| 2819 |  |  |  |  |  |  | length($digest) == 40 ? 'sha1' : | 
| 2820 |  |  |  |  |  |  | length($digest) == 64 ? 'sha256' : | 
| 2821 |  |  |  |  |  |  | return IO::Socket::SSL->_internal_error( | 
| 2822 |  |  |  |  |  |  | "cannot detect hash algorithm from fingerprint '$_'",9); | 
| 2823 | 11 |  |  |  |  | 20 | $algo = lc($algo); | 
| 2824 | 11 |  | 100 |  |  | 100 | push @accept_fp,[ $algo, $pubkey || '', pack('H*',$digest) ] | 
| 2825 |  |  |  |  |  |  | } | 
| 2826 |  |  |  |  |  |  | } | 
| 2827 | 256 |  | 66 |  |  | 1334 | my $verify_fingerprint = @accept_fp && do { | 
| 2828 |  |  |  |  |  |  | my $fail; | 
| 2829 |  |  |  |  |  |  | sub { | 
| 2830 | 17 |  |  | 17 |  | 35 | my ($ok,$cert,$depth) = @_; | 
| 2831 | 17 |  |  |  |  | 33 | $fail = 1 if ! $ok; | 
| 2832 | 17 |  |  |  |  | 33 | return 1 if $depth>0; # to let us continue with verification | 
| 2833 |  |  |  |  |  |  | # Check fingerprint only from top certificate. | 
| 2834 | 12 |  |  |  |  | 18 | my %fp; | 
| 2835 | 12 |  |  |  |  | 25 | for(@accept_fp) { | 
| 2836 | 13 | 100 | 66 |  |  | 124 | my $fp = $fp{$_->[0],$_->[1]} ||= $_->[1] | 
| 2837 |  |  |  |  |  |  | ? Net::SSLeay::X509_pubkey_digest($cert,$algo2digest->($_->[0])) | 
| 2838 |  |  |  |  |  |  | : Net::SSLeay::X509_digest($cert,$algo2digest->($_->[0])); | 
| 2839 | 13 |  |  |  |  | 38 | next if $fp ne $_->[2]; | 
| 2840 | 9 |  |  |  |  | 30 | return 1; | 
| 2841 |  |  |  |  |  |  | } | 
| 2842 | 3 |  |  |  |  | 12 | return ! $fail; | 
| 2843 |  |  |  |  |  |  | } | 
| 2844 |  |  |  |  |  |  | }; | 
| 2845 |  |  |  |  |  |  | my $verify_callback = ( $verify_cb || @accept_fp ) && sub { | 
| 2846 | 201 |  |  | 201 |  | 793 | my ($ok, $ctx_store) = @_; | 
| 2847 | 201 |  |  |  |  | 437 | my ($certname,$cert,$error,$depth); | 
| 2848 | 201 |  |  |  |  | 609 | if ($ctx_store) { | 
| 2849 | 201 |  |  |  |  | 757 | $cert  = Net::SSLeay::X509_STORE_CTX_get_current_cert($ctx_store); | 
| 2850 | 201 |  |  |  |  | 592 | $error = Net::SSLeay::X509_STORE_CTX_get_error($ctx_store); | 
| 2851 | 201 |  |  |  |  | 489 | $depth = Net::SSLeay::X509_STORE_CTX_get_error_depth($ctx_store); | 
| 2852 | 201 |  |  |  |  | 2227 | $certname = | 
| 2853 |  |  |  |  |  |  | Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($cert)). | 
| 2854 |  |  |  |  |  |  | Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($cert)); | 
| 2855 | 201 |  | 66 |  |  | 980 | $error &&= Net::SSLeay::ERR_error_string($error); | 
| 2856 |  |  |  |  |  |  | } | 
| 2857 | 201 |  |  |  |  | 556 | $DEBUG>=3 && DEBUG( "ok=$ok [$depth] $certname" ); | 
| 2858 | 201 |  |  |  |  | 827 | $ok = $verify_cb->($ok,$ctx_store,$certname,$error,$cert,$depth) if $verify_cb; | 
| 2859 | 201 |  |  |  |  | 672 | $ok = $verify_fingerprint->($ok,$cert,$depth) if $verify_fingerprint && $cert; | 
| 2860 | 201 |  |  |  |  | 122383 | return $ok; | 
| 2861 | 256 |  | 100 |  |  | 2993 | }; | 
| 2862 |  |  |  |  |  |  |  | 
| 2863 | 256 | 50 |  |  |  | 2007 | if ( $^O eq 'darwin' ) { | 
| 2864 |  |  |  |  |  |  | # explicitly set error code to disable use of apples TEA patch | 
| 2865 |  |  |  |  |  |  | # https://hynek.me/articles/apple-openssl-verification-surprises/ | 
| 2866 | 0 |  |  |  |  | 0 | my $vcb = $verify_callback; | 
| 2867 |  |  |  |  |  |  | $verify_callback = sub { | 
| 2868 | 0 | 0 |  | 0 |  | 0 | my $rv = $vcb ? &$vcb : $_[0]; | 
| 2869 | 0 | 0 |  |  |  | 0 | if ( $rv != 1 ) { | 
| 2870 |  |  |  |  |  |  | # 50 - X509_V_ERR_APPLICATION_VERIFICATION: application verification failure | 
| 2871 | 0 |  |  |  |  | 0 | Net::SSLeay::X509_STORE_CTX_set_error($_[1], 50); | 
| 2872 |  |  |  |  |  |  | } | 
| 2873 | 0 |  |  |  |  | 0 | return $rv; | 
| 2874 | 0 |  |  |  |  | 0 | }; | 
| 2875 |  |  |  |  |  |  | } | 
| 2876 |  |  |  |  |  |  | Net::SSLeay::CTX_set_verify($_, $verify_mode, $verify_callback) | 
| 2877 | 256 |  |  |  |  | 3584 | for (values %ctx); | 
| 2878 |  |  |  |  |  |  |  | 
| 2879 | 256 |  |  |  |  | 896 | my $staple_callback = $arg_hash->{SSL_ocsp_staple_callback}; | 
| 2880 | 256 | 100 | 66 |  |  | 2746 | if ( !$is_server && $can_ocsp_staple && ! $verify_fingerprint) { | 
|  |  |  | 100 |  |  |  |  | 
| 2881 | 156 |  |  |  |  | 1329 | $self->{ocsp_cache} = $arg_hash->{SSL_ocsp_cache}; | 
| 2882 |  |  |  |  |  |  | my $status_cb = sub { | 
| 2883 | 81 |  |  | 81 |  | 478 | my ($ssl,$resp) = @_; | 
| 2884 | 81 | 50 |  |  |  | 574 | my $iossl = $SSL_OBJECT{$ssl} or | 
| 2885 |  |  |  |  |  |  | die "no IO::Socket::SSL object found for SSL $ssl"; | 
| 2886 | 81 | 50 |  |  |  | 347 | $iossl->[1] and do { | 
| 2887 |  |  |  |  |  |  | # we must return with 1 or it will be called again | 
| 2888 |  |  |  |  |  |  | # and because we have no SSL object we must make the error global | 
| 2889 | 0 |  |  |  |  | 0 | Carp::cluck($IO::Socket::SSL::SSL_ERROR | 
| 2890 |  |  |  |  |  |  | = "OCSP callback on server side"); | 
| 2891 | 0 |  |  |  |  | 0 | return 1; | 
| 2892 |  |  |  |  |  |  | }; | 
| 2893 | 81 |  |  |  |  | 188 | $iossl = $iossl->[0]; | 
| 2894 |  |  |  |  |  |  |  | 
| 2895 |  |  |  |  |  |  | # if we have a callback use this | 
| 2896 |  |  |  |  |  |  | # callback must not free or copy $resp !! | 
| 2897 | 81 | 50 |  |  |  | 257 | if ( $staple_callback ) { | 
| 2898 | 0 |  |  |  |  | 0 | $staple_callback->($iossl,$resp); | 
| 2899 | 0 |  |  |  |  | 0 | return 1; | 
| 2900 |  |  |  |  |  |  | } | 
| 2901 |  |  |  |  |  |  |  | 
| 2902 |  |  |  |  |  |  | # default callback does verification | 
| 2903 | 81 | 100 |  |  |  | 233 | if ( ! $resp ) { | 
| 2904 | 79 | 50 |  |  |  | 261 | $DEBUG>=3 && DEBUG("did not get stapled OCSP response"); | 
| 2905 | 79 |  |  |  |  | 13880 | return 1; | 
| 2906 |  |  |  |  |  |  | } | 
| 2907 | 2 | 50 |  |  |  | 7 | $DEBUG>=3 && DEBUG("got stapled OCSP response"); | 
| 2908 | 2 |  |  |  |  | 11 | my $status = Net::SSLeay::OCSP_response_status($resp); | 
| 2909 | 2 | 50 |  |  |  | 45 | if ($status != Net::SSLeay::OCSP_RESPONSE_STATUS_SUCCESSFUL()) { | 
| 2910 | 0 | 0 |  |  |  | 0 | $DEBUG>=3 && DEBUG("bad status of stapled OCSP response: ". | 
| 2911 |  |  |  |  |  |  | Net::SSLeay::OCSP_response_status_str($status)); | 
| 2912 | 0 |  |  |  |  | 0 | return 1; | 
| 2913 |  |  |  |  |  |  | } | 
| 2914 | 2 | 50 |  |  |  | 218 | if (!eval { Net::SSLeay::OCSP_response_verify($ssl,$resp) }) { | 
|  | 2 |  |  |  |  | 387 |  | 
| 2915 | 0 | 0 |  |  |  | 0 | $DEBUG>=3 && DEBUG("verify of stapled OCSP response failed"); | 
| 2916 | 0 |  |  |  |  | 0 | return 1; | 
| 2917 |  |  |  |  |  |  | } | 
| 2918 | 2 |  |  |  |  | 29 | my (@results,$hard_error); | 
| 2919 | 2 |  |  |  |  | 16 | my @chain = $iossl->peer_certificates; | 
| 2920 | 2 |  |  |  |  | 8 | for my $cert (@chain) { | 
| 2921 | 6 |  |  |  |  | 14 | my $certid = eval { Net::SSLeay::OCSP_cert2ids($ssl,$cert) }; | 
|  | 6 |  |  |  |  | 537 |  | 
| 2922 | 6 | 100 |  |  |  | 29 | if (!$certid) { | 
| 2923 | 1 | 50 |  |  |  | 5 | $DEBUG>=3 && DEBUG("cannot create OCSP_CERTID: $@"); | 
| 2924 | 1 |  |  |  |  | 3 | push @results,[-1,$@]; | 
| 2925 | 1 |  |  |  |  | 3 | last; | 
| 2926 |  |  |  |  |  |  | } | 
| 2927 | 5 |  |  |  |  | 359 | ($status) = Net::SSLeay::OCSP_response_results($resp,$certid); | 
| 2928 | 5 | 100 | 66 |  |  | 49 | if ($status && $status->[2]) { | 
| 2929 | 2 |  |  |  |  | 4 | my $cache = ${*$iossl}{_SSL_ctx}{ocsp_cache}; | 
|  | 2 |  |  |  |  | 11 |  | 
| 2930 | 2 | 50 |  |  |  | 11 | if (!$status->[1]) { | 
|  |  | 0 |  |  |  |  |  | 
| 2931 | 2 |  |  |  |  | 9 | push @results,[1,$status->[2]{nextUpdate}]; | 
| 2932 | 2 | 50 |  |  |  | 11 | $cache && $cache->put($certid,$status->[2]); | 
| 2933 |  |  |  |  |  |  | } elsif ( $status->[2]{statusType} == | 
| 2934 |  |  |  |  |  |  | Net::SSLeay::V_OCSP_CERTSTATUS_GOOD()) { | 
| 2935 | 0 |  |  |  |  | 0 | push @results,[1,$status->[2]{nextUpdate}]; | 
| 2936 |  |  |  |  |  |  | $cache && $cache->put($certid,{ | 
| 2937 | 0 | 0 |  |  |  | 0 | %{$status->[2]}, | 
|  | 0 |  |  |  |  | 0 |  | 
| 2938 |  |  |  |  |  |  | expire => time()+120, | 
| 2939 |  |  |  |  |  |  | soft_error => $status->[1], | 
| 2940 |  |  |  |  |  |  | }); | 
| 2941 |  |  |  |  |  |  | } else { | 
| 2942 | 0 |  |  |  |  | 0 | push @results,($hard_error = [0,$status->[1]]); | 
| 2943 |  |  |  |  |  |  | $cache && $cache->put($certid,{ | 
| 2944 | 0 | 0 |  |  |  | 0 | %{$status->[2]}, | 
|  | 0 |  |  |  |  | 0 |  | 
| 2945 |  |  |  |  |  |  | hard_error => $status->[1], | 
| 2946 |  |  |  |  |  |  | }); | 
| 2947 |  |  |  |  |  |  | } | 
| 2948 |  |  |  |  |  |  | } | 
| 2949 |  |  |  |  |  |  | } | 
| 2950 |  |  |  |  |  |  | # return result of lead certificate, this should be in chain[0] and | 
| 2951 |  |  |  |  |  |  | # thus result[0], but we better check. But if we had any hard_error | 
| 2952 |  |  |  |  |  |  | # return this instead | 
| 2953 | 2 | 50 | 33 |  |  | 17 | if ($hard_error) { | 
|  |  | 50 |  |  |  |  |  | 
| 2954 | 0 |  |  |  |  | 0 | ${*$iossl}{_SSL_ocsp_verify} = $hard_error; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2955 |  |  |  |  |  |  | } elsif (@results and $chain[0] == $iossl->peer_certificate) { | 
| 2956 | 2 |  |  |  |  | 5 | ${*$iossl}{_SSL_ocsp_verify} = $results[0]; | 
|  | 2 |  |  |  |  | 5 |  | 
| 2957 |  |  |  |  |  |  | } | 
| 2958 | 2 |  |  |  |  | 1487 | return 1; | 
| 2959 | 156 |  |  |  |  | 17528 | }; | 
| 2960 | 156 |  |  |  |  | 2091 | Net::SSLeay::CTX_set_tlsext_status_cb($_,$status_cb) for (values %ctx); | 
| 2961 |  |  |  |  |  |  | } | 
| 2962 |  |  |  |  |  |  |  | 
| 2963 | 256 | 50 |  |  |  | 1204 | if ( my $cl = $arg_hash->{SSL_cipher_list} ) { | 
| 2964 | 256 |  |  |  |  | 839 | for (keys %ctx) { | 
| 2965 |  |  |  |  |  |  | Net::SSLeay::CTX_set_cipher_list($ctx{$_}, ref($cl) | 
| 2966 |  |  |  |  |  |  | ? $cl->{$_} || $cl->{''} || $DEFAULT_SSL_ARGS{SSL_cipher_list} || next | 
| 2967 | 270 | 50 | 0 |  |  | 26091 | : $cl | 
|  |  | 100 |  |  |  |  |  | 
| 2968 |  |  |  |  |  |  | ) || return IO::Socket::SSL->error("Failed to set SSL cipher list"); | 
| 2969 |  |  |  |  |  |  | } | 
| 2970 |  |  |  |  |  |  | } | 
| 2971 | 254 | 50 |  |  |  | 1334 | if ( my $cl = $arg_hash->{SSL_ciphersuites} ) { | 
| 2972 | 0 | 0 |  |  |  | 0 | return IO::Socket::SSL->error("no support for SSL_ciphersuites in Net::SSLeay") | 
| 2973 |  |  |  |  |  |  | if ! $can_ciphersuites; | 
| 2974 | 0 |  |  |  |  | 0 | for (keys %ctx) { | 
| 2975 |  |  |  |  |  |  | Net::SSLeay::CTX_set_ciphersuites($ctx{$_}, ref($cl) | 
| 2976 |  |  |  |  |  |  | ? $cl->{$_} || $cl->{''} || $DEFAULT_SSL_ARGS{SSL_cipher_list} || next | 
| 2977 | 0 | 0 | 0 |  |  | 0 | : $cl | 
|  |  | 0 |  |  |  |  |  | 
| 2978 |  |  |  |  |  |  | ) || return IO::Socket::SSL->error("Failed to set SSL cipher list"); | 
| 2979 |  |  |  |  |  |  | } | 
| 2980 |  |  |  |  |  |  | } | 
| 2981 |  |  |  |  |  |  |  | 
| 2982 |  |  |  |  |  |  | # Main context is default context or any other if no default context. | 
| 2983 | 254 |  | 33 |  |  | 1240 | my $ctx = $ctx{''} || (values %ctx)[0]; | 
| 2984 | 254 | 100 | 66 |  |  | 2576 | if (keys(%ctx) > 1 || ! exists $ctx{''}) { | 
| 2985 | 6 | 50 |  |  |  | 16 | $can_server_sni or return IO::Socket::SSL->_internal_error( | 
| 2986 |  |  |  |  |  |  | "Server side SNI not supported for this openssl/Net::SSLeay",9); | 
| 2987 |  |  |  |  |  |  |  | 
| 2988 |  |  |  |  |  |  | Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, sub { | 
| 2989 | 19 |  |  | 19 |  | 56 | my $ssl = shift; | 
| 2990 | 19 |  |  |  |  | 142 | my $host = Net::SSLeay::get_servername($ssl); | 
| 2991 | 19 | 100 |  |  |  | 93 | $host = '' if ! defined $host; | 
| 2992 | 19 | 50 | 66 |  |  | 176 | my $snictx = $ctx{lc($host)} || $ctx{''} or do { | 
| 2993 | 0 | 0 |  |  |  | 0 | $DEBUG>1 and DEBUG( | 
| 2994 |  |  |  |  |  |  | "cannot get context from servername '$host'"); | 
| 2995 | 0 |  |  |  |  | 0 | return 2; # SSL_TLSEXT_ERR_ALERT_FATAL | 
| 2996 |  |  |  |  |  |  | }; | 
| 2997 | 19 | 50 |  |  |  | 51 | $DEBUG>1 and DEBUG("set context from servername $host"); | 
| 2998 | 19 | 100 |  |  |  | 309 | Net::SSLeay::set_SSL_CTX($ssl,$snictx) if $snictx != $ctx; | 
| 2999 | 19 |  |  |  |  | 528775 | return 0; # SSL_TLSEXT_ERR_OK | 
| 3000 | 6 |  |  |  |  | 102 | }); | 
| 3001 |  |  |  |  |  |  | } | 
| 3002 |  |  |  |  |  |  |  | 
| 3003 | 254 | 50 |  |  |  | 1329 | if ( my $cb = $arg_hash->{SSL_create_ctx_callback} ) { | 
| 3004 | 0 |  |  |  |  | 0 | $cb->($_) for values (%ctx); | 
| 3005 |  |  |  |  |  |  | } | 
| 3006 |  |  |  |  |  |  |  | 
| 3007 | 254 |  |  |  |  | 1783 | $self->{context} = $ctx; | 
| 3008 | 254 |  |  |  |  | 1199 | $self->{verify_mode} = $arg_hash->{SSL_verify_mode}; | 
| 3009 |  |  |  |  |  |  | $self->{ocsp_mode} = | 
| 3010 |  |  |  |  |  |  | defined($arg_hash->{SSL_ocsp_mode}) ? $arg_hash->{SSL_ocsp_mode} : | 
| 3011 | 254 | 100 |  |  |  | 1809 | $self->{verify_mode} ? IO::Socket::SSL::SSL_OCSP_TRY_STAPLE() : | 
|  |  | 100 |  |  |  |  |  | 
| 3012 |  |  |  |  |  |  | 0; | 
| 3013 | 254 | 50 |  |  |  | 992 | $DEBUG>=3 && DEBUG( "new ctx $ctx" ); | 
| 3014 |  |  |  |  |  |  |  | 
| 3015 | 254 | 50 |  |  |  | 1477 | if ( my $cache = $arg_hash->{SSL_session_cache} ) { | 
|  |  | 100 |  |  |  |  |  | 
| 3016 |  |  |  |  |  |  | # use predefined cache | 
| 3017 | 0 |  |  |  |  | 0 | $self->{session_cache} = $cache | 
| 3018 |  |  |  |  |  |  | } elsif ( my $size = $arg_hash->{SSL_session_cache_size}) { | 
| 3019 | 3 |  |  |  |  | 63 | $self->{session_cache} = IO::Socket::SSL::Session_Cache->new( $size ); | 
| 3020 |  |  |  |  |  |  | } | 
| 3021 |  |  |  |  |  |  |  | 
| 3022 |  |  |  |  |  |  |  | 
| 3023 | 254 | 50 | 66 |  |  | 1062 | if ($self->{session_cache} and %sess_cb) { | 
| 3024 | 0 |  |  |  |  | 0 | Net::SSLeay::CTX_set_session_cache_mode($ctx, | 
| 3025 |  |  |  |  |  |  | Net::SSLeay::SESS_CACHE_CLIENT()); | 
| 3026 | 0 |  |  |  |  | 0 | my $cache = $self->{session_cache}; | 
| 3027 |  |  |  |  |  |  | $sess_cb{new}($ctx, sub { | 
| 3028 | 0 |  |  | 0 |  | 0 | my ($ssl,$session) = @_; | 
| 3029 | 0 |  | 0 |  |  | 0 | my $self = ($SSL_OBJECT{$ssl} || do { | 
| 3030 |  |  |  |  |  |  | warn "callback session new: no known SSL object for $ssl"; | 
| 3031 |  |  |  |  |  |  | return; | 
| 3032 |  |  |  |  |  |  | })->[0]; | 
| 3033 | 0 |  |  |  |  | 0 | my $args = ${*$self}{_SSL_arguments}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3034 | 0 | 0 |  |  |  | 0 | my $key = $args->{SSL_session_key} or do { | 
| 3035 | 0 |  |  |  |  | 0 | warn "callback session new: no known SSL_session_key for $ssl"; | 
| 3036 | 0 |  |  |  |  | 0 | return; | 
| 3037 |  |  |  |  |  |  | }; | 
| 3038 | 0 | 0 |  |  |  | 0 | $DEBUG>=3 && DEBUG("callback session new <$key> $session"); | 
| 3039 | 0 |  |  |  |  | 0 | Net::SSLeay::SESSION_up_ref($session); | 
| 3040 | 0 |  |  |  |  | 0 | $cache->add_session($key,$session); | 
| 3041 | 0 |  |  |  |  | 0 | }); | 
| 3042 |  |  |  |  |  |  | $sess_cb{remove}($ctx, sub { | 
| 3043 | 0 |  |  | 0 |  | 0 | my ($ctx,$session) = @_; | 
| 3044 | 0 | 0 |  |  |  | 0 | $DEBUG>=3 && DEBUG("callback session remove $session"); | 
| 3045 | 0 |  |  |  |  | 0 | $cache->del_session(undef,$session); | 
| 3046 | 0 |  |  |  |  | 0 | }); | 
| 3047 |  |  |  |  |  |  | } | 
| 3048 |  |  |  |  |  |  |  | 
| 3049 | 254 |  |  |  |  | 1735 | return $self; | 
| 3050 |  |  |  |  |  |  | } | 
| 3051 |  |  |  |  |  |  |  | 
| 3052 |  |  |  |  |  |  |  | 
| 3053 |  |  |  |  |  |  | sub has_session_cache { | 
| 3054 | 0 |  |  | 0 |  | 0 | return defined shift->{session_cache}; | 
| 3055 |  |  |  |  |  |  | } | 
| 3056 |  |  |  |  |  |  |  | 
| 3057 |  |  |  |  |  |  |  | 
| 3058 | 0 |  |  | 0 |  | 0 | sub CLONE { %CTX_CREATED_IN_THIS_THREAD = (); } | 
| 3059 |  |  |  |  |  |  | sub DESTROY { | 
| 3060 | 259 |  |  | 259 |  | 18631 | my $self = shift; | 
| 3061 | 259 | 100 |  |  |  | 1172 | if ( my $ctx = $self->{context} ) { | 
| 3062 | 252 | 50 |  |  |  | 1226 | $DEBUG>=3 && DEBUG("free ctx $ctx open=".join( " ",keys %CTX_CREATED_IN_THIS_THREAD )); | 
| 3063 | 252 | 50 | 33 |  |  | 1189 | if (!$use_threads or delete $CTX_CREATED_IN_THIS_THREAD{$ctx} ) { | 
| 3064 |  |  |  |  |  |  | # remove any verify callback for this context | 
| 3065 | 252 | 100 |  |  |  | 894 | if ( $self->{verify_mode}) { | 
| 3066 | 92 | 50 |  |  |  | 255 | $DEBUG>=3 && DEBUG("free ctx $ctx callback" ); | 
| 3067 | 92 |  |  |  |  | 1785 | Net::SSLeay::CTX_set_verify($ctx, 0,undef); | 
| 3068 |  |  |  |  |  |  | } | 
| 3069 | 252 | 50 |  |  |  | 947 | if ( $self->{ocsp_error_ref}) { | 
| 3070 | 0 | 0 |  |  |  | 0 | $DEBUG>=3 && DEBUG("free ctx $ctx tlsext_status_cb" ); | 
| 3071 | 0 |  |  |  |  | 0 | Net::SSLeay::CTX_set_tlsext_status_cb($ctx,undef); | 
| 3072 |  |  |  |  |  |  | } | 
| 3073 | 252 | 50 |  |  |  | 861 | $DEBUG>=3 && DEBUG("OK free ctx $ctx" ); | 
| 3074 | 252 |  |  |  |  | 11078 | Net::SSLeay::CTX_free($ctx); | 
| 3075 |  |  |  |  |  |  | } | 
| 3076 |  |  |  |  |  |  | } | 
| 3077 | 259 |  |  |  |  | 844 | delete(@{$self}{'context','session_cache'}); | 
|  | 259 |  |  |  |  | 23392 |  | 
| 3078 |  |  |  |  |  |  | } | 
| 3079 |  |  |  |  |  |  |  | 
| 3080 |  |  |  |  |  |  | package IO::Socket::SSL::Session_Cache; | 
| 3081 |  |  |  |  |  |  | *DEBUG = *IO::Socket::SSL::DEBUG; | 
| 3082 |  |  |  |  |  |  | use constant { | 
| 3083 | 80 |  |  |  |  | 353894 | SESSION => 0, | 
| 3084 |  |  |  |  |  |  | KEY     => 1, | 
| 3085 |  |  |  |  |  |  | GNEXT   => 2, | 
| 3086 |  |  |  |  |  |  | GPREV   => 3, | 
| 3087 |  |  |  |  |  |  | SNEXT   => 4, | 
| 3088 |  |  |  |  |  |  | SPREV   => 5, | 
| 3089 | 80 |  |  | 80 |  | 536747 | }; | 
|  | 80 |  |  |  |  | 230 |  | 
| 3090 |  |  |  |  |  |  |  | 
| 3091 |  |  |  |  |  |  | sub new { | 
| 3092 | 3 |  |  | 3 |  | 16 | my ($class, $size) = @_; | 
| 3093 | 3 | 50 |  |  |  | 11 | $size>0 or return; | 
| 3094 | 3 |  |  |  |  | 68 | return bless { | 
| 3095 |  |  |  |  |  |  | room  => $size, | 
| 3096 |  |  |  |  |  |  | ghead => undef, | 
| 3097 |  |  |  |  |  |  | shead => {}, | 
| 3098 |  |  |  |  |  |  | }, $class; | 
| 3099 |  |  |  |  |  |  | } | 
| 3100 |  |  |  |  |  |  |  | 
| 3101 |  |  |  |  |  |  | sub add_session { | 
| 3102 | 16 |  |  | 16 |  | 209 | my ($self, $key, $session) = @_; | 
| 3103 |  |  |  |  |  |  |  | 
| 3104 |  |  |  |  |  |  | # create new | 
| 3105 | 16 |  |  |  |  | 39 | my $v = []; | 
| 3106 | 16 |  |  |  |  | 43 | $v->[SESSION] = $session; | 
| 3107 | 16 |  |  |  |  | 31 | $v->[KEY] = $key; | 
| 3108 | 16 | 50 |  |  |  | 53 | $DEBUG>=3 && DEBUG("add_session($key,$session)"); | 
| 3109 | 16 |  |  |  |  | 60 | _add_entry($self,$v); | 
| 3110 |  |  |  |  |  |  | } | 
| 3111 |  |  |  |  |  |  |  | 
| 3112 |  |  |  |  |  |  | sub replace_session { | 
| 3113 | 0 |  |  | 0 |  | 0 | my ($self, $key, $session) = @_; | 
| 3114 | 0 |  |  |  |  | 0 | $self->del_session($key); | 
| 3115 | 0 |  |  |  |  | 0 | $self->add_session($key, $session); | 
| 3116 |  |  |  |  |  |  | } | 
| 3117 |  |  |  |  |  |  |  | 
| 3118 |  |  |  |  |  |  | sub del_session { | 
| 3119 | 1 |  |  | 1 |  | 38 | my ($self, $key, $session) = @_; | 
| 3120 |  |  |  |  |  |  | my ($head,$inext) = $key | 
| 3121 | 1 | 50 |  |  |  | 5 | ? ($self->{shead}{$key},SNEXT) : ($self->{ghead},GNEXT); | 
| 3122 | 1 |  |  |  |  | 2 | my $v = $head; | 
| 3123 | 1 |  |  |  |  | 2 | my @del; | 
| 3124 | 1 |  |  |  |  | 5 | while ($v) { | 
| 3125 | 3 | 50 |  |  |  | 7 | if (!$session) { | 
|  |  | 0 |  |  |  |  |  | 
| 3126 | 3 |  |  |  |  | 6 | push @del,$v | 
| 3127 |  |  |  |  |  |  | } elsif ($v->[SESSION] == $session) { | 
| 3128 | 0 |  |  |  |  | 0 | push @del, $v; | 
| 3129 | 0 |  |  |  |  | 0 | last; | 
| 3130 |  |  |  |  |  |  | } | 
| 3131 | 3 |  |  |  |  | 5 | $v = $v->[$inext]; | 
| 3132 | 3 | 100 |  |  |  | 8 | last if $v == $head; | 
| 3133 |  |  |  |  |  |  | } | 
| 3134 | 1 | 0 | 0 |  |  | 4 | $DEBUG>=3 && DEBUG("del_session(" | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 3135 |  |  |  |  |  |  | . ($key ? $key : "undef") | 
| 3136 |  |  |  |  |  |  | . ($session ? ",$session) -> " : ") -> ") | 
| 3137 |  |  |  |  |  |  | .  (~~@del || 'none')); | 
| 3138 | 1 |  |  |  |  | 3 | for (@del) { | 
| 3139 | 3 |  |  |  |  | 7 | _del_entry($self,$_); | 
| 3140 | 3 | 50 |  |  |  | 8 | Net::SSLeay::SESSION_free($_->[SESSION]) if $_->[SESSION]; | 
| 3141 | 3 |  |  |  |  | 16 | @$_ = (); | 
| 3142 |  |  |  |  |  |  | } | 
| 3143 | 1 |  |  |  |  | 12 | return ~~@del; | 
| 3144 |  |  |  |  |  |  | } | 
| 3145 |  |  |  |  |  |  |  | 
| 3146 |  |  |  |  |  |  | sub get_session { | 
| 3147 | 16 |  |  | 16 |  | 80 | my ($self, $key, $session) = @_; | 
| 3148 | 16 |  |  |  |  | 37 | my $v = $self->{shead}{$key}; | 
| 3149 | 16 | 100 |  |  |  | 38 | if ($session) { | 
| 3150 | 3 |  |  |  |  | 6 | my $shead = $v; | 
| 3151 | 3 |  |  |  |  | 11 | while ($v) { | 
| 3152 | 3 | 50 |  |  |  | 14 | $DEBUG>=3 && DEBUG("check $session - $v->[SESSION]"); | 
| 3153 | 3 | 50 |  |  |  | 15 | last if $v->[SESSION] == $session; | 
| 3154 | 0 |  |  |  |  | 0 | $v = $v->[SNEXT]; | 
| 3155 | 0 | 0 |  |  |  | 0 | $v = undef if $v == $shead; # session not found | 
| 3156 |  |  |  |  |  |  | } | 
| 3157 |  |  |  |  |  |  | } | 
| 3158 | 16 | 100 |  |  |  | 38 | if ($v) { | 
| 3159 | 12 |  |  |  |  | 66 | _del_entry($self, $v); # remove | 
| 3160 | 12 |  |  |  |  | 36 | _add_entry($self, $v); # and add back on top | 
| 3161 |  |  |  |  |  |  | } | 
| 3162 | 16 | 0 |  |  |  | 36 | $DEBUG>=3 && DEBUG("get_session($key" | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 3163 |  |  |  |  |  |  | . ( $session ? ",$session) -> " : ") -> ") | 
| 3164 |  |  |  |  |  |  | . ($v? $v->[SESSION]:"none")); | 
| 3165 | 16 |  | 66 |  |  | 103 | return $v && $v->[SESSION]; | 
| 3166 |  |  |  |  |  |  | } | 
| 3167 |  |  |  |  |  |  |  | 
| 3168 |  |  |  |  |  |  | sub _add_entry { | 
| 3169 | 28 |  |  | 28 |  | 64 | my ($self,$v) = @_; | 
| 3170 | 28 |  |  |  |  | 135 | for( | 
| 3171 |  |  |  |  |  |  | [ SNEXT, SPREV, \$self->{shead}{$v->[KEY]} ], | 
| 3172 |  |  |  |  |  |  | [ GNEXT, GPREV, \$self->{ghead} ], | 
| 3173 |  |  |  |  |  |  | ) { | 
| 3174 | 56 |  |  |  |  | 102 | my ($inext,$iprev,$rhead) = @$_; | 
| 3175 | 56 | 100 |  |  |  | 114 | if ($$rhead) { | 
| 3176 | 38 |  |  |  |  | 67 | $v->[$inext] = $$rhead; | 
| 3177 | 38 |  |  |  |  | 56 | $v->[$iprev] = ${$rhead}->[$iprev]; | 
|  | 38 |  |  |  |  | 77 |  | 
| 3178 | 38 |  |  |  |  | 59 | ${$rhead}->[$iprev][$inext] = $v; | 
|  | 38 |  |  |  |  | 65 |  | 
| 3179 | 38 |  |  |  |  | 49 | ${$rhead}->[$iprev] = $v; | 
|  | 38 |  |  |  |  | 57 |  | 
| 3180 |  |  |  |  |  |  | } else { | 
| 3181 | 18 |  |  |  |  | 39 | $v->[$inext] = $v->[$iprev] = $v; | 
| 3182 |  |  |  |  |  |  | } | 
| 3183 | 56 |  |  |  |  | 118 | $$rhead = $v; | 
| 3184 |  |  |  |  |  |  | } | 
| 3185 |  |  |  |  |  |  |  | 
| 3186 | 28 |  |  |  |  | 67 | $self->{room}--; | 
| 3187 |  |  |  |  |  |  |  | 
| 3188 |  |  |  |  |  |  | # drop old entries if necessary | 
| 3189 | 28 | 100 |  |  |  | 88 | if ($self->{room}<0) { | 
| 3190 | 1 |  |  |  |  | 2 | my $l = $self->{ghead}[GPREV]; | 
| 3191 | 1 |  |  |  |  | 4 | _del_entry($self,$l); | 
| 3192 | 1 | 50 |  |  |  | 6 | Net::SSLeay::SESSION_free($l->[SESSION]) if $l->[SESSION]; | 
| 3193 | 1 |  |  |  |  | 4 | @$l = (); | 
| 3194 |  |  |  |  |  |  | } | 
| 3195 |  |  |  |  |  |  | } | 
| 3196 |  |  |  |  |  |  |  | 
| 3197 |  |  |  |  |  |  | sub _del_entry { | 
| 3198 | 16 |  |  | 16 |  | 35 | my ($self,$v) = @_; | 
| 3199 | 16 |  |  |  |  | 67 | for( | 
| 3200 |  |  |  |  |  |  | [ SNEXT, SPREV, \$self->{shead}{$v->[KEY]} ], | 
| 3201 |  |  |  |  |  |  | [ GNEXT, GPREV, \$self->{ghead} ], | 
| 3202 |  |  |  |  |  |  | ) { | 
| 3203 | 32 |  |  |  |  | 96 | my ($inext,$iprev,$rhead) = @$_; | 
| 3204 | 32 | 50 |  |  |  | 128 | $$rhead or return; | 
| 3205 | 32 |  |  |  |  | 51 | $v->[$inext][$iprev] = $v->[$iprev]; | 
| 3206 | 32 |  |  |  |  | 50 | $v->[$iprev][$inext] = $v->[$inext]; | 
| 3207 | 32 | 100 |  |  |  | 105 | if ($v != $$rhead) { | 
|  |  | 100 |  |  |  |  |  | 
| 3208 |  |  |  |  |  |  | # not removed from top of list | 
| 3209 |  |  |  |  |  |  | } elsif ($v->[$inext] == $v) { | 
| 3210 |  |  |  |  |  |  | # was only element on list, drop list | 
| 3211 | 12 | 100 |  |  |  | 28 | if ($inext == SNEXT) { | 
| 3212 | 10 |  |  |  |  | 37 | delete $self->{shead}{$v->[KEY]}; | 
| 3213 |  |  |  |  |  |  | } else { | 
| 3214 | 2 |  |  |  |  | 6 | $$rhead = undef; | 
| 3215 |  |  |  |  |  |  | } | 
| 3216 |  |  |  |  |  |  | } else { | 
| 3217 |  |  |  |  |  |  | # was top element, keep others | 
| 3218 | 12 |  |  |  |  | 26 | $$rhead = $v->[$inext]; | 
| 3219 |  |  |  |  |  |  | } | 
| 3220 |  |  |  |  |  |  | } | 
| 3221 | 16 |  |  |  |  | 74 | $self->{room}++; | 
| 3222 |  |  |  |  |  |  | } | 
| 3223 |  |  |  |  |  |  |  | 
| 3224 |  |  |  |  |  |  | sub _dump { | 
| 3225 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 3226 |  |  |  |  |  |  |  | 
| 3227 | 0 |  |  |  |  | 0 | my %v2i; | 
| 3228 | 0 |  |  |  |  | 0 | my $v = $self->{ghead}; | 
| 3229 | 0 |  |  |  |  | 0 | while ($v) { | 
| 3230 | 0 | 0 |  |  |  | 0 | exists $v2i{$v} and die; | 
| 3231 | 0 |  |  |  |  | 0 | $v2i{$v} = int(keys %v2i); | 
| 3232 | 0 |  |  |  |  | 0 | $v = $v->[GNEXT]; | 
| 3233 | 0 | 0 |  |  |  | 0 | last if $v == $self->{ghead}; | 
| 3234 |  |  |  |  |  |  | } | 
| 3235 |  |  |  |  |  |  |  | 
| 3236 | 0 |  |  |  |  | 0 | my $out = "room: $self->{room}\nghead:\n"; | 
| 3237 | 0 |  |  |  |  | 0 | $v = $self->{ghead}; | 
| 3238 | 0 |  |  |  |  | 0 | while ($v) { | 
| 3239 |  |  |  |  |  |  | $out .= sprintf(" - [%d] <%d,%d> '%s' <%s>\n", | 
| 3240 | 0 |  |  |  |  | 0 | $v2i{$v}, $v2i{$v->[GPREV]}, $v2i{$v->[GNEXT]}, | 
| 3241 |  |  |  |  |  |  | $v->[KEY], $v->[SESSION]); | 
| 3242 | 0 |  |  |  |  | 0 | $v = $v->[GNEXT]; | 
| 3243 | 0 | 0 |  |  |  | 0 | last if $v == $self->{ghead}; | 
| 3244 |  |  |  |  |  |  | } | 
| 3245 | 0 |  |  |  |  | 0 | $out .= "shead:\n"; | 
| 3246 | 0 |  |  |  |  | 0 | for my $key (sort keys %{$self->{shead}}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 3247 | 0 |  |  |  |  | 0 | $out .= " - '$key'\n"; | 
| 3248 | 0 |  |  |  |  | 0 | my $shead = $self->{shead}{$key}; | 
| 3249 | 0 |  |  |  |  | 0 | my $v = $shead; | 
| 3250 | 0 |  |  |  |  | 0 | while ($v) { | 
| 3251 |  |  |  |  |  |  | $out .= sprintf("   - [%d] <%d,%d> '%s' <%s>\n", | 
| 3252 | 0 |  |  |  |  | 0 | $v2i{$v}, $v2i{$v->[SPREV]}, $v2i{$v->[SNEXT]}, | 
| 3253 |  |  |  |  |  |  | $v->[KEY], $v->[SESSION]); | 
| 3254 | 0 |  |  |  |  | 0 | $v = $v->[SNEXT]; | 
| 3255 | 0 | 0 |  |  |  | 0 | last if $v == $shead; | 
| 3256 |  |  |  |  |  |  | } | 
| 3257 |  |  |  |  |  |  | } | 
| 3258 | 0 |  |  |  |  | 0 | return $out; | 
| 3259 |  |  |  |  |  |  | } | 
| 3260 |  |  |  |  |  |  |  | 
| 3261 |  |  |  |  |  |  | sub DESTROY { | 
| 3262 | 2 |  |  | 2 |  | 7 | my $self = shift; | 
| 3263 | 2 |  |  |  |  | 7 | delete $self->{shead}; | 
| 3264 | 2 |  |  |  |  | 7 | my $v = delete $self->{ghead}; | 
| 3265 | 2 |  |  |  |  | 4 | while ($v) { | 
| 3266 | 7 | 100 |  |  |  | 78 | Net::SSLeay::SESSION_free($v->[SESSION]) if $v->[SESSION]; | 
| 3267 | 7 |  |  |  |  | 11 | my $next = $v->[GNEXT]; | 
| 3268 | 7 |  |  |  |  | 13 | @$v = (); | 
| 3269 | 7 |  |  |  |  | 182 | $v = $next; | 
| 3270 |  |  |  |  |  |  | } | 
| 3271 |  |  |  |  |  |  | } | 
| 3272 |  |  |  |  |  |  |  | 
| 3273 |  |  |  |  |  |  |  | 
| 3274 |  |  |  |  |  |  |  | 
| 3275 |  |  |  |  |  |  | package IO::Socket::SSL::OCSP_Cache; | 
| 3276 |  |  |  |  |  |  |  | 
| 3277 |  |  |  |  |  |  | sub new { | 
| 3278 | 4 |  |  | 4 |  | 44603 | my ($class,$size) = @_; | 
| 3279 | 4 |  | 50 |  |  | 76 | return bless { | 
| 3280 |  |  |  |  |  |  | '' => { _lru => 0, size => $size || 100 } | 
| 3281 |  |  |  |  |  |  | },$class; | 
| 3282 |  |  |  |  |  |  | } | 
| 3283 |  |  |  |  |  |  | sub get { | 
| 3284 | 5 |  |  | 5 |  | 16 | my ($self,$id) = @_; | 
| 3285 | 5 | 50 |  |  |  | 33 | my $e = $self->{$id} or return; | 
| 3286 | 0 |  |  |  |  | 0 | $e->{_lru} = $self->{''}{_lru}++; | 
| 3287 | 0 | 0 | 0 |  |  | 0 | if ( $e->{expire} && time()<$e->{expire}) { | 
| 3288 | 0 |  |  |  |  | 0 | delete $self->{$id}; | 
| 3289 | 0 |  |  |  |  | 0 | return; | 
| 3290 |  |  |  |  |  |  | } | 
| 3291 | 0 | 0 | 0 |  |  | 0 | if ( $e->{nextUpdate} && time()<$e->{nextUpdate} ) { | 
| 3292 | 0 |  |  |  |  | 0 | delete $self->{$id}; | 
| 3293 | 0 |  |  |  |  | 0 | return; | 
| 3294 |  |  |  |  |  |  | } | 
| 3295 | 0 |  |  |  |  | 0 | return $e; | 
| 3296 |  |  |  |  |  |  | } | 
| 3297 |  |  |  |  |  |  |  | 
| 3298 |  |  |  |  |  |  | sub put { | 
| 3299 | 5 |  |  | 5 |  | 15 | my ($self,$id,$e) = @_; | 
| 3300 | 5 |  |  |  |  | 14 | $self->{$id} = $e; | 
| 3301 | 5 |  |  |  |  | 26 | $e->{_lru} = $self->{''}{_lru}++; | 
| 3302 | 5 |  |  |  |  | 44 | my $del = keys(%$self) - $self->{''}{size}; | 
| 3303 | 5 | 50 |  |  |  | 18 | if ($del>0) { | 
| 3304 | 0 |  |  |  |  | 0 | my @k = sort { $self->{$a}{_lru} <=> $self->{$b}{_lru} } keys %$self; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3305 | 0 |  |  |  |  | 0 | delete @{$self}{ splice(@k,0,$del) }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3306 |  |  |  |  |  |  | } | 
| 3307 | 5 |  |  |  |  | 23 | return $e; | 
| 3308 |  |  |  |  |  |  | } | 
| 3309 |  |  |  |  |  |  |  | 
| 3310 |  |  |  |  |  |  | package IO::Socket::SSL::OCSP_Resolver; | 
| 3311 |  |  |  |  |  |  | *DEBUG = *IO::Socket::SSL::DEBUG; | 
| 3312 |  |  |  |  |  |  |  | 
| 3313 |  |  |  |  |  |  | # create a new resolver | 
| 3314 |  |  |  |  |  |  | # $ssl - the ssl object | 
| 3315 |  |  |  |  |  |  | # $cache - OCSP_Cache object (put,get) | 
| 3316 |  |  |  |  |  |  | # $failhard - flag if we should fail hard on OCSP problems | 
| 3317 |  |  |  |  |  |  | # $certs - list of certs to verify | 
| 3318 |  |  |  |  |  |  | sub new { | 
| 3319 | 4 |  |  | 4 |  | 18 | my ($class,$ssl,$cache,$failhard,$certs) = @_; | 
| 3320 | 4 |  |  |  |  | 11 | my (%todo,$done,$hard_error,@soft_error); | 
| 3321 | 4 |  |  |  |  | 14 | for my $cert (@$certs) { | 
| 3322 |  |  |  |  |  |  | # skip entries which have no OCSP uri or where we cannot get a certid | 
| 3323 |  |  |  |  |  |  | # (e.g. self-signed or where we don't have the issuer) | 
| 3324 | 8 |  |  |  |  | 68 | my $subj = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($cert)); | 
| 3325 | 8 | 100 |  |  |  | 124 | my $uri = Net::SSLeay::P_X509_get_ocsp_uri($cert) or do { | 
| 3326 | 3 | 50 |  |  |  | 20 | $DEBUG>2 && DEBUG("no URI for certificate $subj"); | 
| 3327 | 3 |  |  |  |  | 15 | push @soft_error,"no ocsp_uri for $subj"; | 
| 3328 | 3 |  |  |  |  | 8 | next; | 
| 3329 |  |  |  |  |  |  | }; | 
| 3330 | 5 | 50 |  |  |  | 19 | my $certid = eval { Net::SSLeay::OCSP_cert2ids($ssl,$cert) } or do { | 
|  | 5 |  |  |  |  | 136 |  | 
| 3331 | 0 | 0 |  |  |  | 0 | $DEBUG>2 && DEBUG("no OCSP_CERTID for certificate $subj: $@"); | 
| 3332 | 0 |  |  |  |  | 0 | push @soft_error,"no certid for $subj: $@"; | 
| 3333 | 0 |  |  |  |  | 0 | next; | 
| 3334 |  |  |  |  |  |  | }; | 
| 3335 | 5 | 50 |  |  |  | 28 | if (!($done = $cache->get($certid))) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 3336 | 5 |  |  |  |  | 12 | push @{ $todo{$uri}{ids} }, $certid; | 
|  | 5 |  |  |  |  | 28 |  | 
| 3337 | 5 |  |  |  |  | 13 | push @{ $todo{$uri}{subj} }, $subj; | 
|  | 5 |  |  |  |  | 20 |  | 
| 3338 |  |  |  |  |  |  | } elsif ( $done->{hard_error} ) { | 
| 3339 |  |  |  |  |  |  | # one error is enough to fail validation | 
| 3340 | 0 |  |  |  |  | 0 | $hard_error = $done->{hard_error}; | 
| 3341 | 0 |  |  |  |  | 0 | %todo = (); | 
| 3342 | 0 |  |  |  |  | 0 | last; | 
| 3343 |  |  |  |  |  |  | } elsif ( $done->{soft_error} ) { | 
| 3344 | 0 |  |  |  |  | 0 | push @soft_error,$done->{soft_error}; | 
| 3345 |  |  |  |  |  |  | } | 
| 3346 |  |  |  |  |  |  | } | 
| 3347 | 4 |  |  |  |  | 40 | while ( my($uri,$v) = each %todo) { | 
| 3348 | 5 |  |  |  |  | 13 | my $ids = $v->{ids}; | 
| 3349 | 5 |  |  |  |  | 164 | $v->{req} = Net::SSLeay::i2d_OCSP_REQUEST( | 
| 3350 |  |  |  |  |  |  | Net::SSLeay::OCSP_ids2req(@$ids)); | 
| 3351 |  |  |  |  |  |  | } | 
| 3352 | 4 | 50 | 0 |  |  | 17 | $hard_error ||= '' if ! %todo; | 
| 3353 | 4 | 100 |  |  |  | 64 | return bless { | 
| 3354 |  |  |  |  |  |  | ssl => $ssl, | 
| 3355 |  |  |  |  |  |  | cache => $cache, | 
| 3356 |  |  |  |  |  |  | failhard => $failhard, | 
| 3357 |  |  |  |  |  |  | hard_error => $hard_error, | 
| 3358 |  |  |  |  |  |  | soft_error => @soft_error ? join("; ",@soft_error) : undef, | 
| 3359 |  |  |  |  |  |  | todo => \%todo, | 
| 3360 |  |  |  |  |  |  | },$class; | 
| 3361 |  |  |  |  |  |  | } | 
| 3362 |  |  |  |  |  |  |  | 
| 3363 |  |  |  |  |  |  | # return current result, e.g. '' for no error, else error | 
| 3364 |  |  |  |  |  |  | # if undef we have no final result yet | 
| 3365 | 0 |  |  | 0 |  | 0 | sub hard_error { return shift->{hard_error} } | 
| 3366 | 2 |  |  | 2 |  | 22 | sub soft_error { return shift->{soft_error} } | 
| 3367 |  |  |  |  |  |  |  | 
| 3368 |  |  |  |  |  |  | # return hash with uri => ocsp_request_data for open requests | 
| 3369 |  |  |  |  |  |  | sub requests { | 
| 3370 | 10 |  |  | 10 |  | 59 | my $todo = shift()->{todo}; | 
| 3371 | 10 |  |  |  |  | 51 | return map { ($_,$todo->{$_}{req}) } keys %$todo; | 
|  | 7 |  |  |  |  | 47 |  | 
| 3372 |  |  |  |  |  |  | } | 
| 3373 |  |  |  |  |  |  |  | 
| 3374 |  |  |  |  |  |  | # add new response | 
| 3375 |  |  |  |  |  |  | sub add_response { | 
| 3376 | 5 |  |  | 5 |  | 20 | my ($self,$uri,$resp) = @_; | 
| 3377 | 5 |  |  |  |  | 22 | my $todo = delete $self->{todo}{$uri}; | 
| 3378 | 5 | 50 | 33 |  |  | 46 | return $self->{error} if ! $todo || $self->{error}; | 
| 3379 |  |  |  |  |  |  |  | 
| 3380 | 5 |  |  |  |  | 18 | my ($req,@soft_error,@hard_error); | 
| 3381 |  |  |  |  |  |  |  | 
| 3382 |  |  |  |  |  |  | # do we have a response | 
| 3383 | 5 | 50 |  |  |  | 24 | if (!$resp) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 3384 |  |  |  |  |  |  | @soft_error = "http request for OCSP failed; subject: ". | 
| 3385 | 0 |  |  |  |  | 0 | join("; ",@{$todo->{subj}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3386 |  |  |  |  |  |  |  | 
| 3387 |  |  |  |  |  |  | # is it a valid OCSP_RESPONSE | 
| 3388 | 5 |  |  |  |  | 458 | } elsif ( ! eval { $resp = Net::SSLeay::d2i_OCSP_RESPONSE($resp) }) { | 
| 3389 |  |  |  |  |  |  | @soft_error = "invalid response (no OCSP_RESPONSE); subject: ". | 
| 3390 | 0 |  |  |  |  | 0 | join("; ",@{$todo->{subj}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3391 |  |  |  |  |  |  | # hopefully short-time error | 
| 3392 |  |  |  |  |  |  | $self->{cache}->put($_,{ | 
| 3393 |  |  |  |  |  |  | soft_error => "@soft_error", | 
| 3394 |  |  |  |  |  |  | expire => time()+10, | 
| 3395 | 0 |  |  |  |  | 0 | }) for (@{$todo->{ids}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3396 |  |  |  |  |  |  | # is the OCSP response status success | 
| 3397 |  |  |  |  |  |  | } elsif ( | 
| 3398 |  |  |  |  |  |  | ( my $status = Net::SSLeay::OCSP_response_status($resp)) | 
| 3399 |  |  |  |  |  |  | != Net::SSLeay::OCSP_RESPONSE_STATUS_SUCCESSFUL() | 
| 3400 |  |  |  |  |  |  | ){ | 
| 3401 |  |  |  |  |  |  | @soft_error = "OCSP response failed: ". | 
| 3402 |  |  |  |  |  |  | Net::SSLeay::OCSP_response_status_str($status). | 
| 3403 | 0 |  |  |  |  | 0 | "; subject: ".join("; ",@{$todo->{subj}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3404 |  |  |  |  |  |  | # hopefully short-time error | 
| 3405 |  |  |  |  |  |  | $self->{cache}->put($_,{ | 
| 3406 |  |  |  |  |  |  | soft_error => "@soft_error", | 
| 3407 |  |  |  |  |  |  | expire => time()+10, | 
| 3408 | 0 |  |  |  |  | 0 | }) for (@{$todo->{ids}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3409 |  |  |  |  |  |  |  | 
| 3410 |  |  |  |  |  |  | # does nonce match the request and can the signature be verified | 
| 3411 |  |  |  |  |  |  | } elsif ( ! eval { | 
| 3412 | 5 |  |  |  |  | 124 | $req = Net::SSLeay::d2i_OCSP_REQUEST($todo->{req}); | 
| 3413 | 5 |  |  |  |  | 1134 | Net::SSLeay::OCSP_response_verify($self->{ssl},$resp,$req); | 
| 3414 |  |  |  |  |  |  | }) { | 
| 3415 | 0 | 0 |  |  |  | 0 | if ($@) { | 
| 3416 | 0 |  |  |  |  | 0 | @soft_error = $@ | 
| 3417 |  |  |  |  |  |  | } else { | 
| 3418 | 0 |  |  |  |  | 0 | my @err; | 
| 3419 | 0 |  |  |  |  | 0 | while ( my $err = Net::SSLeay::ERR_get_error()) { | 
| 3420 | 0 |  |  |  |  | 0 | push @soft_error, Net::SSLeay::ERR_error_string($err); | 
| 3421 |  |  |  |  |  |  | } | 
| 3422 |  |  |  |  |  |  | @soft_error = 'failed to verify OCSP response; subject: '. | 
| 3423 | 0 | 0 |  |  |  | 0 | join("; ",@{$todo->{subj}}) if ! @soft_error; | 
|  | 0 |  |  |  |  | 0 |  | 
| 3424 |  |  |  |  |  |  | } | 
| 3425 |  |  |  |  |  |  | # configuration problem or we don't know the signer | 
| 3426 |  |  |  |  |  |  | $self->{cache}->put($_,{ | 
| 3427 |  |  |  |  |  |  | soft_error => "@soft_error", | 
| 3428 |  |  |  |  |  |  | expire => time()+120, | 
| 3429 | 0 |  |  |  |  | 0 | }) for (@{$todo->{ids}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3430 |  |  |  |  |  |  |  | 
| 3431 |  |  |  |  |  |  | # extract results from response | 
| 3432 |  |  |  |  |  |  | } elsif ( my @result = | 
| 3433 | 5 |  |  |  |  | 515 | Net::SSLeay::OCSP_response_results($resp,@{$todo->{ids}})) { | 
| 3434 | 5 |  |  |  |  | 36 | my (@found,@miss); | 
| 3435 | 5 |  |  |  |  | 24 | for my $rv (@result) { | 
| 3436 | 5 | 50 |  |  |  | 22 | if ($rv->[2]) { | 
| 3437 | 5 |  |  |  |  | 27 | push @found,$rv->[0]; | 
| 3438 | 5 | 50 |  |  |  | 17 | if (!$rv->[1]) { | 
|  |  | 0 |  |  |  |  |  | 
| 3439 |  |  |  |  |  |  | # no error | 
| 3440 | 5 |  |  |  |  | 37 | $self->{cache}->put($rv->[0],$rv->[2]); | 
| 3441 |  |  |  |  |  |  | } elsif ( $rv->[2]{statusType} == | 
| 3442 |  |  |  |  |  |  | Net::SSLeay::V_OCSP_CERTSTATUS_GOOD()) { | 
| 3443 |  |  |  |  |  |  | # soft error, like response after nextUpdate | 
| 3444 |  |  |  |  |  |  | push @soft_error,$rv->[1]."; subject: ". | 
| 3445 | 0 |  |  |  |  | 0 | join("; ",@{$todo->{subj}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3446 |  |  |  |  |  |  | $self->{cache}->put($rv->[0],{ | 
| 3447 | 0 |  |  |  |  | 0 | %{$rv->[2]}, | 
|  | 0 |  |  |  |  | 0 |  | 
| 3448 |  |  |  |  |  |  | soft_error => "@soft_error", | 
| 3449 |  |  |  |  |  |  | expire => time()+120, | 
| 3450 |  |  |  |  |  |  | }); | 
| 3451 |  |  |  |  |  |  | } else { | 
| 3452 |  |  |  |  |  |  | # hard error | 
| 3453 | 0 |  |  |  |  | 0 | $self->{cache}->put($rv->[0],$rv->[2]); | 
| 3454 |  |  |  |  |  |  | push @hard_error, $rv->[1]."; subject: ". | 
| 3455 | 0 |  |  |  |  | 0 | join("; ",@{$todo->{subj}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3456 |  |  |  |  |  |  | } | 
| 3457 |  |  |  |  |  |  | } else { | 
| 3458 | 0 |  |  |  |  | 0 | push @miss,$rv->[0]; | 
| 3459 |  |  |  |  |  |  | } | 
| 3460 |  |  |  |  |  |  | } | 
| 3461 | 5 | 50 | 33 |  |  | 25 | if (@miss && @found) { | 
| 3462 |  |  |  |  |  |  | # we sent multiple responses, but server answered only to one | 
| 3463 |  |  |  |  |  |  | # try again | 
| 3464 | 0 |  |  |  |  | 0 | $self->{todo}{$uri} = $todo; | 
| 3465 | 0 |  |  |  |  | 0 | $todo->{ids} = \@miss; | 
| 3466 | 0 |  |  |  |  | 0 | $todo->{req} = Net::SSLeay::i2d_OCSP_REQUEST( | 
| 3467 |  |  |  |  |  |  | Net::SSLeay::OCSP_ids2req(@miss)); | 
| 3468 | 0 | 0 |  |  |  | 0 | $DEBUG>=2 && DEBUG("$uri just answered ".@found." of ".(@found+@miss)." requests"); | 
| 3469 |  |  |  |  |  |  | } | 
| 3470 |  |  |  |  |  |  | } else { | 
| 3471 |  |  |  |  |  |  | @soft_error = "no data in response; subject: ". | 
| 3472 | 0 |  |  |  |  | 0 | join("; ",@{$todo->{subj}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3473 |  |  |  |  |  |  | # probably configuration problem | 
| 3474 |  |  |  |  |  |  | $self->{cache}->put($_,{ | 
| 3475 |  |  |  |  |  |  | soft_error => "@soft_error", | 
| 3476 |  |  |  |  |  |  | expire => time()+120, | 
| 3477 | 0 |  |  |  |  | 0 | }) for (@{$todo->{ids}}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3478 |  |  |  |  |  |  | } | 
| 3479 |  |  |  |  |  |  |  | 
| 3480 | 5 | 50 |  |  |  | 42 | Net::SSLeay::OCSP_REQUEST_free($req) if $req; | 
| 3481 | 5 | 50 |  |  |  | 22 | if ($self->{failhard}) { | 
| 3482 | 0 |  |  |  |  | 0 | push @hard_error,@soft_error; | 
| 3483 | 0 |  |  |  |  | 0 | @soft_error = (); | 
| 3484 |  |  |  |  |  |  | } | 
| 3485 | 5 | 50 |  |  |  | 20 | if (@soft_error) { | 
| 3486 | 0 | 0 |  |  |  | 0 | $self->{soft_error} .= "; " if $self->{soft_error}; | 
| 3487 | 0 |  |  |  |  | 0 | $self->{soft_error} .= "$uri: ".join('; ',@soft_error); | 
| 3488 |  |  |  |  |  |  | } | 
| 3489 | 5 | 50 |  |  |  | 18 | if (@hard_error) { | 
|  |  | 100 |  |  |  |  |  | 
| 3490 | 0 |  |  |  |  | 0 | $self->{hard_error} = "$uri: ".join('; ',@hard_error); | 
| 3491 | 0 |  |  |  |  | 0 | %{$self->{todo}} = (); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3492 | 5 |  |  |  |  | 20 | } elsif ( ! %{$self->{todo}} ) { | 
| 3493 | 4 |  |  |  |  | 13 | $self->{hard_error} = '' | 
| 3494 |  |  |  |  |  |  | } | 
| 3495 | 5 |  |  |  |  | 776 | return $self->{hard_error}; | 
| 3496 |  |  |  |  |  |  | } | 
| 3497 |  |  |  |  |  |  |  | 
| 3498 |  |  |  |  |  |  | # make all necessary requests to get OCSP responses blocking | 
| 3499 |  |  |  |  |  |  | sub resolve_blocking { | 
| 3500 | 4 |  |  | 4 |  | 49 | my ($self,%args) = @_; | 
| 3501 | 4 |  |  |  |  | 21 | while ( my %todo = $self->requests ) { | 
| 3502 | 4 | 50 |  |  |  | 14 | eval { require HTTP::Tiny } or die "need HTTP::Tiny installed"; | 
|  | 4 |  |  |  |  | 60 |  | 
| 3503 |  |  |  |  |  |  | # OCSP responses have their own signature, so we don't need SSL verification | 
| 3504 | 4 |  |  |  |  | 48 | my $ua = HTTP::Tiny->new(verify_SSL => 0,%args); | 
| 3505 | 4 |  |  |  |  | 578 | while (my ($uri,$reqdata) = each %todo) { | 
| 3506 | 5 | 50 |  |  |  | 22 | $DEBUG && DEBUG("sending OCSP request to $uri"); | 
| 3507 | 5 |  |  |  |  | 49 | my $resp = $ua->request('POST',$uri, { | 
| 3508 |  |  |  |  |  |  | headers => { 'Content-type' => 'application/ocsp-request' }, | 
| 3509 |  |  |  |  |  |  | content => $reqdata | 
| 3510 |  |  |  |  |  |  | }); | 
| 3511 | 5 | 50 |  |  |  | 793940 | $DEBUG && DEBUG("got  OCSP response from $uri code=$resp->{status}"); | 
| 3512 |  |  |  |  |  |  | defined ($self->add_response($uri, | 
| 3513 | 5 | 100 | 33 |  |  | 69 | $resp->{success} && $resp->{content})) | 
| 3514 |  |  |  |  |  |  | && last; | 
| 3515 |  |  |  |  |  |  | } | 
| 3516 |  |  |  |  |  |  | } | 
| 3517 | 4 | 50 |  |  |  | 18 | $DEBUG>=2 && DEBUG("no more open OCSP requests"); | 
| 3518 | 4 |  |  |  |  | 44 | return $self->{hard_error}; | 
| 3519 |  |  |  |  |  |  | } | 
| 3520 |  |  |  |  |  |  |  | 
| 3521 |  |  |  |  |  |  | package IO::Socket::SSL::Trace; | 
| 3522 |  |  |  |  |  |  | *DEBUG = *IO::Socket::SSL::DEBUG; | 
| 3523 |  |  |  |  |  |  |  | 
| 3524 |  |  |  |  |  |  | # Exhaustive list of constants we need for tracing | 
| 3525 |  |  |  |  |  |  | my %trace_constants = map { $_ => eval { Net::SSLeay->$_ } || -1 } qw( | 
| 3526 |  |  |  |  |  |  | SSL2_VERSION | 
| 3527 |  |  |  |  |  |  | SSL3_VERSION | 
| 3528 |  |  |  |  |  |  | TLS1_VERSION | 
| 3529 |  |  |  |  |  |  | TLS1_1_VERSION | 
| 3530 |  |  |  |  |  |  | TLS1_2_VERSION | 
| 3531 |  |  |  |  |  |  | TLS1_3_VERSION | 
| 3532 |  |  |  |  |  |  | DTLS1_VERSION | 
| 3533 |  |  |  |  |  |  | DTLS1_2_VERSION | 
| 3534 |  |  |  |  |  |  | DTLS1_BAD_VER | 
| 3535 |  |  |  |  |  |  | SSL3_RT_INNER_CONTENT_TYPE | 
| 3536 |  |  |  |  |  |  | SSL3_RT_CHANGE_CIPHER_SPEC | 
| 3537 |  |  |  |  |  |  | SSL3_RT_ALERT | 
| 3538 |  |  |  |  |  |  | SSL3_RT_HEADER | 
| 3539 |  |  |  |  |  |  | SSL3_RT_HANDSHAKE | 
| 3540 |  |  |  |  |  |  | SSL3_RT_APPLICATION_DATA | 
| 3541 |  |  |  |  |  |  | SSL2_MT_ERROR | 
| 3542 |  |  |  |  |  |  | SSL2_MT_CLIENT_HELLO | 
| 3543 |  |  |  |  |  |  | SSL2_MT_CLIENT_MASTER_KEY | 
| 3544 |  |  |  |  |  |  | SSL2_MT_CLIENT_FINISHED | 
| 3545 |  |  |  |  |  |  | SSL2_MT_SERVER_HELLO | 
| 3546 |  |  |  |  |  |  | SSL2_MT_SERVER_VERIFY | 
| 3547 |  |  |  |  |  |  | SSL2_MT_SERVER_FINISHED | 
| 3548 |  |  |  |  |  |  | SSL2_MT_REQUEST_CERTIFICATE | 
| 3549 |  |  |  |  |  |  | SSL2_MT_CLIENT_CERTIFICATE | 
| 3550 |  |  |  |  |  |  | SSL3_MT_HELLO_REQUEST | 
| 3551 |  |  |  |  |  |  | SSL3_MT_CLIENT_HELLO | 
| 3552 |  |  |  |  |  |  | SSL3_MT_SERVER_HELLO | 
| 3553 |  |  |  |  |  |  | SSL3_MT_NEWSESSION_TICKET | 
| 3554 |  |  |  |  |  |  | SSL3_MT_CERTIFICATE | 
| 3555 |  |  |  |  |  |  | SSL3_MT_SERVER_KEY_EXCHANGE | 
| 3556 |  |  |  |  |  |  | SSL3_MT_CLIENT_KEY_EXCHANGE | 
| 3557 |  |  |  |  |  |  | SSL3_MT_CERTIFICATE_REQUEST | 
| 3558 |  |  |  |  |  |  | SSL3_MT_SERVER_DONE | 
| 3559 |  |  |  |  |  |  | SSL3_MT_CERTIFICATE_VERIFY | 
| 3560 |  |  |  |  |  |  | SSL3_MT_FINISHED | 
| 3561 |  |  |  |  |  |  | SSL3_MT_CERTIFICATE_STATUS | 
| 3562 |  |  |  |  |  |  | SSL3_MT_ENCRYPTED_EXTENSIONS | 
| 3563 |  |  |  |  |  |  | SSL3_MT_SUPPLEMENTAL_DATA | 
| 3564 |  |  |  |  |  |  | SSL3_MT_END_OF_EARLY_DATA | 
| 3565 |  |  |  |  |  |  | SSL3_MT_KEY_UPDATE | 
| 3566 |  |  |  |  |  |  | SSL3_MT_NEXT_PROTO | 
| 3567 |  |  |  |  |  |  | SSL3_MT_MESSAGE_HASH | 
| 3568 |  |  |  |  |  |  | ); | 
| 3569 |  |  |  |  |  |  |  | 
| 3570 |  |  |  |  |  |  | # | 
| 3571 |  |  |  |  |  |  | # Major versions | 
| 3572 |  |  |  |  |  |  | # | 
| 3573 |  |  |  |  |  |  | $trace_constants{SSL2_VERSION_MAJOR} = $trace_constants{SSL2_VERSION} >> 8; | 
| 3574 |  |  |  |  |  |  | $trace_constants{SSL3_VERSION_MAJOR} = $trace_constants{SSL3_VERSION} >> 8; | 
| 3575 |  |  |  |  |  |  |  | 
| 3576 |  |  |  |  |  |  | # | 
| 3577 |  |  |  |  |  |  | # Mapping between trace constant and version string | 
| 3578 |  |  |  |  |  |  | # | 
| 3579 |  |  |  |  |  |  | my %tc_ver2s; | 
| 3580 |  |  |  |  |  |  | for ( | 
| 3581 |  |  |  |  |  |  | [ SSL2_VERSION    => "SSLv2" ], | 
| 3582 |  |  |  |  |  |  | [ SSL2_VERSION    => "SSLv2" ], | 
| 3583 |  |  |  |  |  |  | [ SSL3_VERSION    => "SSLv3" ], | 
| 3584 |  |  |  |  |  |  | [ TLS1_VERSION    => "TLSv1.0" ], | 
| 3585 |  |  |  |  |  |  | [ TLS1_1_VERSION  => "TLSv1.1" ], | 
| 3586 |  |  |  |  |  |  | [ TLS1_2_VERSION  => "TLSv1.2" ], | 
| 3587 |  |  |  |  |  |  | [ TLS1_3_VERSION  => "TLSv1.3" ], | 
| 3588 |  |  |  |  |  |  | [ DTLS1_VERSION   => "DTLSv1.0" ], | 
| 3589 |  |  |  |  |  |  | [ DTLS1_2_VERSION => "DTLSv1.2" ], | 
| 3590 |  |  |  |  |  |  | [ DTLS1_BAD_VER   => "DTLSv1.0 (bad)" ] | 
| 3591 |  |  |  |  |  |  | ) { | 
| 3592 |  |  |  |  |  |  | next if $trace_constants{$_->[0]} == -1; | 
| 3593 |  |  |  |  |  |  | $tc_ver2s{$trace_constants{$_->[0]}} = $_->[1]; | 
| 3594 |  |  |  |  |  |  | } | 
| 3595 |  |  |  |  |  |  |  | 
| 3596 |  |  |  |  |  |  | my %tc_type2s; | 
| 3597 |  |  |  |  |  |  | for ( | 
| 3598 |  |  |  |  |  |  | [ SSL3_RT_HEADER             => "TLS header" ], | 
| 3599 |  |  |  |  |  |  | [ SSL3_RT_CHANGE_CIPHER_SPEC => "TLS change cipher" ], | 
| 3600 |  |  |  |  |  |  | [ SSL3_RT_ALERT              => "TLS alert" ], | 
| 3601 |  |  |  |  |  |  | [ SSL3_RT_HANDSHAKE          => "TLS handshake" ], | 
| 3602 |  |  |  |  |  |  | [ SSL3_RT_APPLICATION_DATA   => "TLS app data" ] | 
| 3603 |  |  |  |  |  |  | ) { | 
| 3604 |  |  |  |  |  |  | next if $trace_constants{$_->[0]} == -1; | 
| 3605 |  |  |  |  |  |  | $tc_type2s{$trace_constants{$_->[0]}} = $_->[1]; | 
| 3606 |  |  |  |  |  |  | } | 
| 3607 |  |  |  |  |  |  |  | 
| 3608 |  |  |  |  |  |  | my %tc_msgtype2s; | 
| 3609 |  |  |  |  |  |  | for( | 
| 3610 |  |  |  |  |  |  | [ SSL2_MT_ERROR               => "Error" ], | 
| 3611 |  |  |  |  |  |  | [ SSL2_MT_CLIENT_HELLO        => "Client hello" ], | 
| 3612 |  |  |  |  |  |  | [ SSL2_MT_CLIENT_MASTER_KEY   => "Client key" ], | 
| 3613 |  |  |  |  |  |  | [ SSL2_MT_CLIENT_FINISHED     => "Client finished" ], | 
| 3614 |  |  |  |  |  |  | [ SSL2_MT_SERVER_HELLO        => "Server hello" ], | 
| 3615 |  |  |  |  |  |  | [ SSL2_MT_SERVER_VERIFY       => "Server verify" ], | 
| 3616 |  |  |  |  |  |  | [ SSL2_MT_SERVER_FINISHED     => "Server finished" ], | 
| 3617 |  |  |  |  |  |  | [ SSL2_MT_REQUEST_CERTIFICATE => "Request CERT" ], | 
| 3618 |  |  |  |  |  |  | [ SSL2_MT_REQUEST_CERTIFICATE => "Client CERT" ] | 
| 3619 |  |  |  |  |  |  | ) { | 
| 3620 |  |  |  |  |  |  | next if $trace_constants{$_->[0]} == -1; | 
| 3621 |  |  |  |  |  |  | $tc_msgtype2s{$trace_constants{SSL2_VERSION_MAJOR}, $trace_constants{$_->[0]}} = $_->[1]; | 
| 3622 |  |  |  |  |  |  | } | 
| 3623 |  |  |  |  |  |  | for( | 
| 3624 |  |  |  |  |  |  | [ SSL3_MT_HELLO_REQUEST        => "Hello request" ], | 
| 3625 |  |  |  |  |  |  | [ SSL3_MT_CLIENT_HELLO         => "Client hello" ], | 
| 3626 |  |  |  |  |  |  | [ SSL3_MT_SERVER_HELLO         => "Server hello" ], | 
| 3627 |  |  |  |  |  |  | [ SSL3_MT_NEWSESSION_TICKET    => "Newsession Ticket" ], | 
| 3628 |  |  |  |  |  |  | [ SSL3_MT_CERTIFICATE          => "Certificate" ], | 
| 3629 |  |  |  |  |  |  | [ SSL3_MT_SERVER_KEY_EXCHANGE  => "Server key exchange" ], | 
| 3630 |  |  |  |  |  |  | [ SSL3_MT_CLIENT_KEY_EXCHANGE  => "Client key exchange" ], | 
| 3631 |  |  |  |  |  |  | [ SSL3_MT_CERTIFICATE_REQUEST  => "Request CERT" ], | 
| 3632 |  |  |  |  |  |  | [ SSL3_MT_SERVER_DONE          => "Server finished" ], | 
| 3633 |  |  |  |  |  |  | [ SSL3_MT_CERTIFICATE_VERIFY   => "CERT verify" ], | 
| 3634 |  |  |  |  |  |  | [ SSL3_MT_FINISHED             => "Finished" ], | 
| 3635 |  |  |  |  |  |  | [ SSL3_MT_CERTIFICATE_STATUS   => "Certificate Status" ], | 
| 3636 |  |  |  |  |  |  | [ SSL3_MT_ENCRYPTED_EXTENSIONS => "Encrypted Extensions" ], | 
| 3637 |  |  |  |  |  |  | [ SSL3_MT_SUPPLEMENTAL_DATA    => "Supplemental data" ], | 
| 3638 |  |  |  |  |  |  | [ SSL3_MT_END_OF_EARLY_DATA    => "End of early data" ], | 
| 3639 |  |  |  |  |  |  | [ SSL3_MT_KEY_UPDATE           => "Key update" ], | 
| 3640 |  |  |  |  |  |  | [ SSL3_MT_NEXT_PROTO           => "Next protocol" ], | 
| 3641 |  |  |  |  |  |  | [ SSL3_MT_MESSAGE_HASH         => "Message hash" ] | 
| 3642 |  |  |  |  |  |  | ) { | 
| 3643 |  |  |  |  |  |  | next if $trace_constants{$_->[0]} == -1; | 
| 3644 |  |  |  |  |  |  | $tc_msgtype2s{$trace_constants{SSL3_VERSION_MAJOR}, $trace_constants{$_->[0]}} = $_->[1]; | 
| 3645 |  |  |  |  |  |  | } | 
| 3646 |  |  |  |  |  |  |  | 
| 3647 |  |  |  |  |  |  | # | 
| 3648 |  |  |  |  |  |  | # Translation of curl ossl_trace | 
| 3649 |  |  |  |  |  |  | # | 
| 3650 |  |  |  |  |  |  |  | 
| 3651 |  |  |  |  |  |  | sub ossl_trace { | 
| 3652 | 0 | 0 |  | 0 |  | 0 | $DEBUG>=2 or return; | 
| 3653 | 0 |  |  |  |  | 0 | my ($direction, $ssl_ver, $content_type, $buf, $len, $ssl) = @_; | 
| 3654 |  |  |  |  |  |  |  | 
| 3655 | 0 |  | 0 |  |  | 0 | my $verstr = $tc_ver2s{$ssl_ver} || "(version=$ssl_ver)"; | 
| 3656 |  |  |  |  |  |  |  | 
| 3657 |  |  |  |  |  |  | # Log progress for interesting records only (like Handshake or Alert), skip | 
| 3658 |  |  |  |  |  |  | # all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0). | 
| 3659 |  |  |  |  |  |  | # For TLS 1.3, skip notification of the decrypted inner Content-Type. | 
| 3660 |  |  |  |  |  |  |  | 
| 3661 | 0 | 0 | 0 |  |  | 0 | if ($ssl_ver | 
|  |  |  | 0 |  |  |  |  | 
| 3662 |  |  |  |  |  |  | && ($content_type != $trace_constants{SSL3_RT_HEADER}) | 
| 3663 |  |  |  |  |  |  | && ($content_type != $trace_constants{SSL3_RT_INNER_CONTENT_TYPE}) | 
| 3664 |  |  |  |  |  |  | ) { | 
| 3665 |  |  |  |  |  |  |  | 
| 3666 |  |  |  |  |  |  | # the info given when the version is zero is not that useful for us | 
| 3667 | 0 |  |  |  |  | 0 | $ssl_ver >>= 8;  # check the upper 8 bits only below */ | 
| 3668 |  |  |  |  |  |  |  | 
| 3669 |  |  |  |  |  |  | # SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL | 
| 3670 |  |  |  |  |  |  | # always pass-up content-type as 0. But the interesting message-type | 
| 3671 |  |  |  |  |  |  | # is at 'buf[0]'. | 
| 3672 |  |  |  |  |  |  |  | 
| 3673 |  |  |  |  |  |  | my $tls_rt_name = ($ssl_ver == $trace_constants{SSL3_VERSION_MAJOR} && $content_type) | 
| 3674 | 0 | 0 | 0 |  |  | 0 | ? $tc_type2s{$content_type} || "TLS Unknown (type=$content_type)" | 
|  |  |  | 0 |  |  |  |  | 
| 3675 |  |  |  |  |  |  | : ""; | 
| 3676 |  |  |  |  |  |  |  | 
| 3677 | 0 |  |  |  |  | 0 | my $msg_type; | 
| 3678 |  |  |  |  |  |  | my $msg_name; | 
| 3679 | 0 | 0 |  |  |  | 0 | if ($content_type == $trace_constants{SSL3_RT_CHANGE_CIPHER_SPEC}) { | 
|  |  | 0 |  |  |  |  |  | 
| 3680 | 0 |  |  |  |  | 0 | $msg_type = unpack('c1', $buf); | 
| 3681 | 0 |  |  |  |  | 0 | $msg_name = "Change cipher spec"; | 
| 3682 |  |  |  |  |  |  | } elsif ($content_type == $trace_constants{SSL3_RT_ALERT}) { | 
| 3683 | 0 |  |  |  |  | 0 | my @c = unpack('c2', $buf); | 
| 3684 | 0 |  |  |  |  | 0 | $msg_type = ($c[0] << 8) + $c[1]; | 
| 3685 | 0 |  | 0 |  |  | 0 | $msg_name = eval { Net::SSLeay::alert_desc_string_long($msg_type) } || "Unknown alert"; | 
| 3686 |  |  |  |  |  |  | } else { | 
| 3687 | 0 |  |  |  |  | 0 | $msg_type = unpack('c1', $buf); | 
| 3688 | 0 |  | 0 |  |  | 0 | $msg_name = $tc_msgtype2s{$ssl_ver, $msg_type} || "Unknown (ssl_ver=$ssl_ver, msg=$msg_type)"; | 
| 3689 |  |  |  |  |  |  | } | 
| 3690 | 0 | 0 |  |  |  | 0 | DEBUG(sprintf("* %s (%s), %s, %s (%d)", | 
| 3691 |  |  |  |  |  |  | $verstr, $direction ? "OUT" : "IN", $tls_rt_name, $msg_name, $msg_type)); | 
| 3692 |  |  |  |  |  |  | } | 
| 3693 |  |  |  |  |  |  |  | 
| 3694 |  |  |  |  |  |  | # | 
| 3695 |  |  |  |  |  |  | # Here one might want to hexdump $buf (?) | 
| 3696 |  |  |  |  |  |  | # | 
| 3697 |  |  |  |  |  |  | # $DEBUG>=4 && printf STDERR "%s", hexdump($buf); | 
| 3698 |  |  |  |  |  |  | } | 
| 3699 |  |  |  |  |  |  |  | 
| 3700 |  |  |  |  |  |  |  | 
| 3701 |  |  |  |  |  |  | 1; | 
| 3702 |  |  |  |  |  |  |  | 
| 3703 |  |  |  |  |  |  | __END__ |