1package Net::SSL; 2 3use strict; 4use MIME::Base64; 5use Socket; 6use Carp; 7 8use vars qw(@ISA $VERSION $NEW_ARGS); 9$VERSION = '2.86'; 10$VERSION = eval $VERSION; 11 12require IO::Socket; 13@ISA=qw(IO::Socket::INET); 14 15my %REAL; # private to this package only 16my $DEFAULT_VERSION = '23'; 17my $CRLF = "\015\012"; 18my $SEND_USERAGENT_TO_PROXY = 0; 19 20require Crypt::SSLeay; 21 22sub _default_context { 23 require Crypt::SSLeay::MainContext; 24 Crypt::SSLeay::MainContext::main_ctx(@_); 25} 26 27sub _alarm_set { 28 return if $^O eq 'MSWin32' or $^O eq 'NetWare'; 29 alarm(shift); 30} 31 32sub new { 33 my($class, %arg) = @_; 34 local $NEW_ARGS = \%arg; 35 $class->SUPER::new(%arg); 36} 37 38sub DESTROY { 39 my $self = shift; 40 delete $REAL{$self}; 41 local $@; 42 eval { $self->SUPER::DESTROY; }; 43} 44 45sub configure { 46 my($self, $arg) = @_; 47 my $ssl_version = delete $arg->{SSL_Version} || 48 $ENV{HTTPS_VERSION} || $DEFAULT_VERSION; 49 my $ssl_debug = delete $arg->{SSL_Debug} || $ENV{HTTPS_DEBUG} || 0; 50 51 my $ctx = delete $arg->{SSL_Context} || _default_context($ssl_version); 52 53 *$self->{ssl_ctx} = $ctx; 54 *$self->{ssl_version} = $ssl_version; 55 *$self->{ssl_debug} = $ssl_debug; 56 *$self->{ssl_arg} = $arg; 57 *$self->{ssl_peer_addr} = $arg->{PeerAddr}; 58 *$self->{ssl_peer_port} = $arg->{PeerPort}; 59 *$self->{ssl_new_arg} = $NEW_ARGS; 60 *$self->{ssl_peer_verify} = 0; 61 62 ## Crypt::SSLeay must also aware the SSL Proxy before calling 63 ## $socket->configure($args). Because the $sock->configure() will 64 ## die when failed to resolve the destination server IP address, 65 ## whether the SSL proxy is used or not! 66 ## - dqbai, 2003-05-10 67 if (my $proxy = $self->proxy) { 68 ($arg->{PeerAddr}, $arg->{PeerPort}) = split(':',$proxy); 69 $arg->{PeerPort} || croak("no port given for proxy server $proxy"); 70 } 71 72 $self->SUPER::configure($arg); 73} 74 75# override to make sure there is really a timeout 76sub timeout { 77 shift->SUPER::timeout || 60; 78} 79 80sub blocking { 81 my $self = shift; 82 $self->SUPER::blocking(@_); 83} 84 85sub connect { 86 my $self = shift; 87 88 # configure certs on connect() time, so we can throw an undef 89 # and have LWP understand the error 90 eval { $self->configure_certs() }; 91 if($@) { 92 $@ = "configure certs failed: $@; $!"; 93 $self->die_with_error($@); 94 } 95 96 # finished, update set_verify status 97 if(my $rv = *$self->{ssl_ctx}->set_verify()) { 98 *$self->{ssl_peer_verify} = $rv; 99 } 100 101 if ($self->proxy) { 102 # don't die() in connect, just return undef and set $@ 103 my $proxy_connect = eval { $self->proxy_connect_helper(@_) }; 104 if(! $proxy_connect || $@) { 105 $@ = "proxy connect failed: $@; $!"; 106 croak($@); 107 } 108 } 109 else { 110 *$self->{io_socket_peername}=@_ == 1 ? $_[0] : IO::Socket::sockaddr_in(@_); 111 if(!$self->SUPER::connect(@_)) { 112 # better to die than return here 113 $@ = "Connect failed: $@; $!"; 114 croak($@); 115 } 116 } 117 118 my $debug = *$self->{ssl_debug} || 0; 119 my $ssl = Crypt::SSLeay::Conn->new(*$self->{ssl_ctx}, $debug, $self); 120 my $arg = *$self->{ssl_arg}; 121 my $new_arg = *$self->{ssl_new_arg}; 122 $arg->{SSL_Debug} = $debug; 123 124 # setup SNI if available 125 $ssl->can("set_tlsext_host_name") and 126 $ssl->set_tlsext_host_name(*$self->{ssl_peer_addr}); 127 128 eval { 129 local $SIG{ALRM} = sub { $self->die_with_error("SSL connect timeout") }; 130 # timeout / 2 because we have 3 possible connects here 131 _alarm_set($self->timeout / 2); 132 133 my $rv; 134 { 135 local $SIG{PIPE} = \¨ 136 $rv = eval { $ssl->connect; }; 137 } 138 if (not defined $rv or $rv <= 0) { 139 _alarm_set(0); 140 $ssl = undef; 141 # See RT #59312 142 my %args = (%$arg, %$new_arg); 143 if(*$self->{ssl_version} == 23) { 144 $args{SSL_Version} = 3; 145 # the new connect might itself be overridden with a REAL SSL 146 my $new_ssl = Net::SSL->new(%args); 147 $REAL{$self} = $REAL{$new_ssl} || $new_ssl; 148 return $REAL{$self}; 149 } 150 elsif(*$self->{ssl_version} == 3) { 151 # $self->die_with_error("SSL negotiation failed"); 152 $args{SSL_Version} = 2; 153 my $new_ssl = Net::SSL->new(%args); 154 $REAL{$self} = $new_ssl; 155 return $new_ssl; 156 } 157 else { 158 # don't die, but do set $@, and return undef 159 eval { $self->die_with_error("SSL negotiation failed") }; 160 croak($@); 161 } 162 } 163 _alarm_set(0); 164 }; 165 166 # odd error in eval {} block, maybe alarm outside the evals 167 if($@) { 168 $@ = "$@; $!"; 169 croak($@); 170 } 171 172 # successful SSL connection gets stored 173 *$self->{ssl_ssl} = $ssl; 174 $self; 175} 176 177# Delegate these calls to the Crypt::SSLeay::Conn object 178sub get_peer_certificate { 179 my $self = shift; 180 $self = $REAL{$self} || $self; 181 *$self->{ssl_ssl}->get_peer_certificate(@_); 182} 183 184sub get_peer_verify { 185 my $self = shift; 186 $self = $REAL{$self} || $self; 187 *$self->{ssl_peer_verify}; 188} 189 190sub get_shared_ciphers { 191 my $self = shift; 192 $self = $REAL{$self} || $self; 193 *$self->{ssl_ssl}->get_shared_ciphers(@_); 194} 195 196sub get_cipher { 197 my $self = shift; 198 $self = $REAL{$self} || $self; 199 *$self->{ssl_ssl}->get_cipher(@_); 200} 201 202sub pending { 203 my $self = shift; 204 $self = $REAL{$self} || $self; 205 *$self->{ssl_ssl}->pending(@_); 206} 207 208sub ssl_context { 209 my $self = shift; 210 $self = $REAL{$self} || $self; 211 *$self->{ssl_ctx}; 212} 213 214sub die_with_error { 215 my $self=shift; 216 my $reason=shift; 217 218 my @err; 219 while(my $err=Crypt::SSLeay::Err::get_error_string()) { 220 push @err, $err; 221 } 222 croak("$reason: " . join( ' | ', @err )); 223} 224 225sub read { 226 my $self = shift; 227 $self = $REAL{$self} || $self; 228 229 local $SIG{__DIE__} = \&Carp::confess; 230 local $SIG{ALRM} = sub { $self->die_with_error("SSL read timeout") }; 231 232 _alarm_set($self->timeout); 233 my $n = *$self->{ssl_ssl}->read(@_); 234 _alarm_set(0); 235 $self->die_with_error("read failed") if !defined $n; 236 237 $n; 238} 239 240sub write { 241 my $self = shift; 242 $self = $REAL{$self} || $self; 243 my $n = *$self->{ssl_ssl}->write(@_); 244 $self->die_with_error("write failed") if !defined $n; 245 $n; 246} 247 248*sysread = \&read; 249*syswrite = \&write; 250 251sub print { 252 my $self = shift; 253 $self = $REAL{$self} || $self; 254 # should we care about $, and $\?? 255 # I think it is too expensive... 256 $self->write(join("", @_)); 257} 258 259sub printf { 260 my $self = shift; 261 $self = $REAL{$self} || $self; 262 my $fmt = shift; 263 $self->write(sprintf($fmt, @_)); 264} 265 266sub getchunk { 267 my $self = shift; 268 $self = $REAL{$self} || $self; 269 my $buf = ''; # warnings 270 my $n = $self->read($buf, 32768); 271 return unless defined $n; 272 $buf; 273} 274 275# This is really inefficient, but we only use it for reading the proxy response 276# so that does not really matter. 277sub getline { 278 my $self = shift; 279 $self = $REAL{$self} || $self; 280 my $val=""; 281 my $buf; 282 do { 283 $self->SUPER::recv($buf, 1); 284 $val .= $buf; 285 } until ($buf eq "\n"); 286 287 $val; 288} 289 290# XXX: no way to disable <$sock>?? (tied handle perhaps?) 291 292sub get_lwp_object { 293 my $self = shift; 294 295 my $lwp_object; 296 my $i = 0; 297 while(1) { 298 package DB; 299 my @stack = caller($i++); 300 last unless @stack; 301 my @stack_args = @DB::args; 302 my $stack_object = $stack_args[0] || next; 303 return $stack_object 304 if ref($stack_object) 305 and $stack_object->isa('LWP::UserAgent'); 306 } 307 return undef; 308} 309 310sub send_useragent_to_proxy { 311 if (my $val = shift) { 312 $SEND_USERAGENT_TO_PROXY = $val; 313 } 314 return $SEND_USERAGENT_TO_PROXY; 315} 316 317sub proxy_connect_helper { 318 my $self = shift; 319 320 my $proxy = $self->proxy; 321 my ($proxy_host, $proxy_port) = split(':',$proxy); 322 $proxy_port || croak("no port given for proxy server $proxy"); 323 324 my $proxy_addr = gethostbyname($proxy_host); 325 $proxy_addr || croak("can't resolve proxy server name: $proxy_host, $!"); 326 327 my($peer_port, $peer_addr) = (*$self->{ssl_peer_port}, *$self->{ssl_peer_addr}); 328 $peer_addr || croak("no peer addr given"); 329 $peer_port || croak("no peer port given"); 330 331 # see if the proxy should be bypassed 332 my @no_proxy = split( /\s*,\s*/, $ENV{NO_PROXY} || $ENV{no_proxy} || ''); 333 my $is_proxied = 1; 334 my $domain; 335 for $domain (@no_proxy) { 336 if ($peer_addr =~ /\Q$domain\E$/) { 337 $is_proxied = 0; 338 last; 339 } 340 } 341 342 if ($is_proxied) { 343 $self->SUPER::connect($proxy_port, $proxy_addr) 344 || croak("proxy connect to $proxy_host:$proxy_port failed: $!"); 345 } 346 else { 347 # see RT #57836 348 my $peer_addr_packed = gethostbyname($peer_addr); 349 $self->SUPER::connect($peer_port, $peer_addr_packed) 350 || croak("proxy bypass to $peer_addr:$peer_addr failed: $!"); 351 } 352 353 my $connect_string; 354 if ($ENV{"HTTPS_PROXY_USERNAME"} || $ENV{"HTTPS_PROXY_PASSWORD"}) { 355 my $user = $ENV{"HTTPS_PROXY_USERNAME"}; 356 my $pass = $ENV{"HTTPS_PROXY_PASSWORD"}; 357 358 my $credentials = encode_base64("$user:$pass", ""); 359 $connect_string = join($CRLF, 360 "CONNECT $peer_addr:$peer_port HTTP/1.0", 361 "Proxy-authorization: Basic $credentials" 362 ); 363 } 364 else { 365 $connect_string = "CONNECT $peer_addr:$peer_port HTTP/1.0"; 366 } 367 $connect_string .= $CRLF; 368 369 if (send_useragent_to_proxy()) { 370 my $lwp_object = $self->get_lwp_object; 371 if($lwp_object && $lwp_object->agent) { 372 $connect_string .= "User-Agent: ".$lwp_object->agent.$CRLF; 373 } 374 } 375 376 $connect_string .= $CRLF; 377 $self->SUPER::send($connect_string); 378 379 my $timeout; 380 my $header = ''; 381 382 # See RT #33954 383 # See also RT #64054 384 # Handling incomplete reads and writes better (for some values of 385 # better) may actually make this problem go away, but either way, 386 # there is no good reason to use \d when checking for 0-9 387 388 while ($header !~ m{HTTP/[0-9][.][0-9]\s+200\s+.*$CRLF$CRLF}s) { 389 $timeout = $self->timeout(5) unless length $header; 390 my $n = $self->SUPER::sysread($header, 8192, length $header); 391 last if $n <= 0; 392 } 393 394 $self->timeout($timeout) if defined $timeout; 395 my $conn_ok = ($header =~ m{HTTP/[0-9]+[.][0-9]+\s+200\s+}is) ? 1 : 0; 396 397 if (not $conn_ok) { 398 croak("PROXY ERROR HEADER, could be non-SSL URL:\n$header"); 399 } 400 401 $conn_ok; 402} 403 404# code adapted from LWP::UserAgent, with $ua->env_proxy API 405# see also RT #57836 406sub proxy { 407 my $self = shift; 408 my $proxy_server = $ENV{HTTPS_PROXY} || $ENV{https_proxy}; 409 return unless $proxy_server; 410 411 my($peer_port, $peer_addr) = ( 412 *$self->{ssl_peer_port}, 413 *$self->{ssl_peer_addr} 414 ); 415 $peer_addr || croak("no peer addr given"); 416 $peer_port || croak("no peer port given"); 417 418 # see if the proxy should be bypassed 419 my @no_proxy = split( /\s*,\s*/, 420 $ENV{NO_PROXY} || $ENV{no_proxy} || '' 421 ); 422 my $is_proxied = 1; 423 for my $domain (@no_proxy) { 424 if ($peer_addr =~ /\Q$domain\E\z/) { 425 return; 426 } 427 } 428 429 $proxy_server =~ s|\Ahttps?://||i; 430 # sanitize the end of the string too 431 # see also http://www.nntp.perl.org/group/perl.libwww/2012/10/msg7629.html 432 # and https://github.com/nanis/Crypt-SSLeay/pull/1 433 # Thank you Mark Allen and YigangX Wen 434 $proxy_server =~ s|(:[1-9][0-9]{0,4})/\z|$1|; 435 $proxy_server; 436} 437 438sub configure_certs { 439 my $self = shift; 440 my $ctx = *$self->{ssl_ctx}; 441 442 my $count = 0; 443 for (qw(HTTPS_PKCS12_FILE HTTPS_CERT_FILE HTTPS_KEY_FILE)) { 444 my $file = $ENV{$_}; 445 if ($file) { 446 (-e $file) or croak("$file file does not exist: $!"); 447 (-r $file) or croak("$file file is not readable"); 448 $count++; 449 if (/PKCS12/) { 450 $count++; 451 $ctx->use_pkcs12_file($file ,$ENV{'HTTPS_PKCS12_PASSWORD'}) || croak("failed to load $file: $!"); 452 last; 453 } 454 elsif (/CERT/) { 455 $ctx->use_certificate_file($file ,1) || croak("failed to load $file: $!"); 456 } 457 elsif (/KEY/) { 458 $ctx->use_PrivateKey_file($file, 1) || croak("failed to load $file: $!"); 459 } 460 else { 461 croak("setting $_ not supported"); 462 } 463 } 464 } 465 466 # if both configs are set, then verify them 467 if ($count == 2) { 468 if (! $ctx->check_private_key) { 469 croak("Private key and certificate do not match"); 470 } 471 } 472 473 $count; # number of successful cert loads/checks 474} 475 476sub accept { shift->_unimpl("accept") } 477sub getc { shift->_unimpl("getc") } 478sub ungetc { shift->_unimpl("ungetc") } 479sub getlines { shift->_unimpl("getlines"); } 480 481sub _unimpl { 482 my($self, $meth) = @_; 483 croak("$meth not implemented for Net::SSL sockets"); 484} 485 4861; 487 488__END__ 489 490=head1 NAME 491 492Net::SSL - support for Secure Sockets Layer 493 494=head1 METHODS 495 496=over 4 497 498=item new 499 500Creates a new C<Net::SSL> object. 501 502=item configure 503 504Configures a C<Net::SSL> socket for operation. 505 506=item configure_certs 507 508Sets up a certificate file to use for communicating with on 509the socket. 510 511=item connect 512 513=item die_with_error 514 515=item get_cipher 516 517=item get_lwp_object 518 519Walks up the caller stack and looks for something blessed into 520the C<LWP::UserAgent> namespace and returns it. Vaguely deprecated. 521 522=item get_peer_certificate 523 524Gets the peer certificate from the underlying C<Crypt::SSLeay::Conn> 525object. 526 527=item get_peer_verify 528 529=item get_shared_ciphers 530 531=item getchunk 532 533Attempts to read up to 32KiB of data from the socket. Returns 534C<undef> if nothing was read, otherwise returns the data as 535a scalar. 536 537=item pending 538 539Provides access to OpenSSL's C<pending> attribute on the SSL connection 540object. 541 542=item getline 543 544Reads one character at a time until a newline is encountered, 545and returns the line, including the newline. Grossly 546inefficient. 547 548=item print 549 550Concatenates the input parameters and writes them to the socket. 551Does not honour C<$,> nor C<$/>. Returns the number of bytes written. 552 553=item printf 554 555Performs a C<sprintf> of the input parameters (thus, the first 556parameter must be the format), and writes the result to the socket. 557Returns the number of bytes written. 558 559=item proxy 560 561Returns the hostname of an https proxy server, as specified by the 562C<HTTPS_PROXY> environment variable. 563 564=item proxy_connect_helper 565 566Helps set up a connection through a proxy. 567 568=item read 569 570Performs a read on the socket and returns the result. 571 572=item ssl_context 573 574=item sysread 575 576Is an alias of C<read>. 577 578=item timeout 579 580Returns the timeout value of the socket as defined by the implementing 581class or 60 seconds by default. 582 583=item blocking 584 585Returns a boolean indicating whether the underlying socket is in 586blocking mode. By default, Net::SSL sockets are in blocking mode. 587 588 $sock->blocking(0); # set to non-blocking mode 589 590This method simply calls the underlying C<blocking> method of the 591IO::Socket object. 592 593=item write 594 595Writes the parameters passed in (thus, a list) to the socket. Returns 596the number of bytes written. 597 598=item syswrite 599 600Is an alias of C<write>. 601 602=item accept 603 604Not yet implemented. Will die if called. 605 606=item getc 607 608Not yet implemented. Will die if called. 609 610=item getlines 611 612Not yet implemented. Will die if called. 613 614=item ungetc 615 616Not yet implemented. Will die if called. 617 618=item send_useragent_to_proxy 619 620By default (as of version 2.80 of C<Net::SSL> in the 0.54 distribution 621of Crypt::SSLeay), the user agent string is no longer sent to the 622proxy (but will continue to be sent to the remote host). 623 624The previous behaviour was of marginal benefit, and could cause 625fatal errors in certain scenarios (see CPAN bug #4759) and so no 626longer happens by default. 627 628To reinstate the old behaviour, call C<Net::SSL::send_useragent_to_proxy> 629with a true value (usually 1). 630 631=back 632 633=head1 DIAGNOSTICS 634 635 "no port given for proxy server <proxy>" 636 637A proxy was specified for configuring a socket, but no port number 638was given. Ensure that the proxy is specified as a host:port pair, 639such as C<proxy.example.com:8086>. 640 641 "configure certs failed: <contents of $@>; <contents of $!>" 642 643 "proxy connect failed: <contents of $@>; <contents of $!>" 644 645 "Connect failed: <contents of $@>; <contents of $!>" 646 647During connect(). 648 649=head2 SEE ALSO 650 651=over 4 652 653=item IO::Socket::INET 654 655C<Net::SSL> is implemented by subclassing C<IO::Socket::INET>, hence 656methods not specifically overridden are defined by that package. 657 658=item Net::SSLeay 659 660A package that provides a Perl-level interface to the C<openssl> 661secure sockets layer library. 662 663=back 664 665=cut 666 667