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