File Coverage

blib/lib/IO/Socket/SSL.pm
Criterion Covered Total %
statement 1377 1761 78.1
branch 716 1228 58.3
condition 307 575 53.3
subroutine 147 189 77.7
pod 54 83 65.0
total 2601 3836 67.8


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