Tryag File Manager
Home
-
Turbo Force
Current Path :
/
usr
/
lib
/
perl5
/
vendor_perl
/
5.8.8
/
i386-linux-thread-multi
/
Net
/
Upload File :
New :
File
Dir
//usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/Net/SSL.pm
package Net::SSL; use strict; use vars qw(@ISA $VERSION $NEW_ARGS); use MIME::Base64; use Socket; use Carp; require IO::Socket; @ISA=qw(IO::Socket::INET); my %REAL; # private to this package only my $DEFAULT_VERSION = '23'; my $CRLF = "\015\012"; require Crypt::SSLeay; $VERSION = '2.77'; sub _default_context { require Crypt::SSLeay::MainContext; Crypt::SSLeay::MainContext::main_ctx(@_); } sub new { my($class, %arg) = @_; local $NEW_ARGS = \%arg; $class->SUPER::new(%arg); } sub DESTROY { my $self = shift; delete $REAL{$self}; local $@; eval { $self->SUPER::DESTROY; }; } sub configure { my($self, $arg) = @_; my $ssl_version = delete $arg->{SSL_Version} || $ENV{HTTPS_VERSION} || $DEFAULT_VERSION; my $ssl_debug = delete $arg->{SSL_Debug} || $ENV{HTTPS_DEBUG} || 0; my $ctx = delete $arg->{SSL_Context} || _default_context($ssl_version); *$self->{'ssl_ctx'} = $ctx; *$self->{'ssl_version'} = $ssl_version; *$self->{'ssl_debug'} = $ssl_debug; *$self->{'ssl_arg'} = $arg; *$self->{'ssl_peer_addr'} = $arg->{PeerAddr}; *$self->{'ssl_peer_port'} = $arg->{PeerPort}; *$self->{'ssl_new_arg'} = $NEW_ARGS; *$self->{'ssl_peer_verify'} = 0; ## Crypt::SSLeay must also aware the SSL Proxy before calling ## $socket->configure($args). Because the $sock->configure() will ## die when failed to resolve the destination server IP address, ## whatever the SSL proxy is used or not! ## - dqbai, 2003-05-10 if (my $proxy = $self->proxy) { my ($host, $port) = split(':',$proxy); $port || die("no port given for proxy server $proxy"); $arg->{PeerAddr} = $host; $arg->{PeerPort} = $port; } $self->SUPER::configure($arg); } # override to make sure there is really a timeout sub timeout { shift->SUPER::timeout || 60; } sub connect { my $self = shift; # configure certs on connect() time, so we can throw an undef # and have LWP understand the error eval { $self->configure_certs(); }; if($@) { $@ = "configure certs failed: $@, $!"; $self->die_with_error($@); } # finished, update set_verify status if(my $rv = *$self->{'ssl_ctx'}->set_verify()) { *$self->{'ssl_peer_verify'} = $rv; } if ($self->proxy) { # don't die() in connect, just return undef and set $@ my $proxy_connect = eval { $self->proxy_connect_helper(@_); }; if(! $proxy_connect || $@) { $@ = "proxy connect failed: $@; $!"; die $@; } } else { *$self->{io_socket_peername}=@_ == 1 ? $_[0] : IO::Socket::sockaddr_in(@_); if(!$self->SUPER::connect(@_)) { # better to die than return here $@ = "Connect failed: $@; $!"; die $@; } } # print "ssl_version ".*$self->{ssl_version}."\n"; my $debug = *$self->{'ssl_debug'} || 0; my $ssl = Crypt::SSLeay::Conn->new(*$self->{'ssl_ctx'}, $debug, $self); my $arg = *$self->{ssl_arg}; my $new_arg = *$self->{ssl_new_arg}; $arg->{SSL_Debug} = $debug; eval { local $SIG{ALRM} = sub { $self->die_with_error("SSL connect timeout") }; # timeout / 2 because we have 3 possible connects here alarm_ok() && alarm($self->timeout / 2); my $rv; { local $SIG{PIPE} = \¨ $rv = eval { $ssl->connect; }; } if ($rv <= 0) { alarm_ok() && alarm(0); $ssl = undef; my %args = (%$new_arg, %$arg); if(*$self->{ssl_version} == 23) { $args{SSL_Version} = 3; # the new connect might itself be overridden with a REAL SSL my $new_ssl = Net::SSL->new(%args); $REAL{$self} = $REAL{$new_ssl} || $new_ssl; return $REAL{$self}; } elsif(*$self->{ssl_version} == 3) { # $self->die_with_error("SSL negotiation failed"); $args{SSL_Version} = 2; my $new_ssl = Net::SSL->new(%args); $REAL{$self} = $new_ssl; return $new_ssl; } else { # don't die, but do set $@, and return undef eval { $self->die_with_error("SSL negotiation failed") }; $@ = "$@; $!"; die $@; } } alarm_ok() && alarm(0); }; # odd error in eval {} block, maybe alarm outside the evals if($@) { $! = "$@; $!"; die $@; } # successful SSL connection gets stored *$self->{'ssl_ssl'} = $ssl; $self; } sub accept { die "NYI"; } # Delegate these calls to the Crypt::SSLeay::Conn object sub get_peer_certificate { my $self = shift; $self = $REAL{$self} || $self; *$self->{'ssl_ssl'}->get_peer_certificate(@_); } sub get_peer_verify { my $self = shift; $self = $REAL{$self} || $self; *$self->{'ssl_peer_verify'}; } sub get_shared_ciphers { my $self = shift; $self = $REAL{$self} || $self; *$self->{'ssl_ssl'}->get_shared_ciphers(@_); } sub get_cipher { my $self = shift; $self = $REAL{$self} || $self; *$self->{'ssl_ssl'}->get_cipher(@_); } #sub get_peer_certificate { *{shift()}->{'ssl_ssl'}->get_peer_certificate(@_) } #sub get_shared_ciphers { *{shift()}->{'ssl_ssl'}->get_shared_ciphers(@_) } #sub get_cipher { *{shift()}->{'ssl_ssl'}->get_cipher(@_) } sub ssl_context { my $self = shift; $self = $REAL{$self} || $self; *$self->{'ssl_ctx'}; } sub die_with_error { my $self=shift; my $reason=shift; my $errs=''; while(my $err=Crypt::SSLeay::Err::get_error_string()) { $errs.=" | " if $errs ne ''; $errs.=$err; } die "$reason: $errs"; } sub alarm_ok() { $^O ne 'MSWin32'; } sub read { my $self = shift; $self = $REAL{$self} || $self; local $SIG{__DIE__} = \&Carp::confess; local $SIG{ALRM} = sub { $self->die_with_error("SSL read timeout") }; alarm_ok() && alarm($self->timeout); my $n=*$self->{'ssl_ssl'}->read(@_); $self->die_with_error("read failed") if !defined $n; alarm_ok() && alarm(0); $n; } sub write { my $self = shift; $self = $REAL{$self} || $self; my $n=*$self->{'ssl_ssl'}->write(@_); $self->die_with_error("write failed") if !defined $n; $n; } *sysread = \&read; *syswrite = \&write; sub print { my $self = shift; $self = $REAL{$self} || $self; # should we care about $, and $\?? # I think it is too expensive... $self->write(join("", @_)); } sub printf { my $self = shift; $self = $REAL{$self} || $self; my $fmt = shift; $self->write(sprintf($fmt, @_)); } sub getchunk { my $self = shift; $self = $REAL{$self} || $self; my $buf = ''; # warnings my $n = $self->read($buf, 32*1024); return unless defined $n; $buf; } # In order to implement these we will need to add a buffer in $self. # Is it worth it? sub getc { shift->_unimpl("getc"); } sub ungetc { shift->_unimpl("ungetc"); } #sub getline { shift->_unimpl("getline"); } # This is really inefficient, but we only use it for reading the proxy response # so that does not really matter. sub getline { my $self = shift; $self = $REAL{$self} || $self; my $val=""; my $buf; do { $self->SUPER::recv($buf, 1); $val = $val . $buf; } until ($buf eq "\n"); $val; } sub getlines { shift->_unimpl("getlines"); } # XXX: no way to disable <$sock>?? (tied handle perhaps?) sub _unimpl { my($self, $meth) = @_; die "$meth not implemented for Net::SSL sockets"; } sub get_lwp_object { my $self = shift; my $lwp_object; my $i = 0; while(1) { package DB; my @stack = caller($i++); last unless @stack; my @stack_args = @DB::args; my $stack_object = $stack_args[0] || next; ref($stack_object) || next; if($stack_object->isa('LWP::UserAgent')) { $lwp_object = $stack_object; last; } } $lwp_object; } sub proxy_connect_helper { my $self = shift; my $proxy = $self->proxy; my ($host, $port) = split(':',$proxy); my $conn_ok = 0; my $need_auth = 0; my $auth_basic = 0; my $realm = ""; my $length = 0; my $line = "<noline>"; my $lwp_object = $self->get_lwp_object; my $iaddr = gethostbyname($host); $iaddr || die("can't resolve proxy server name: $host, $!"); $port || die("no port given for proxy server $proxy"); $self->SUPER::connect($port, $iaddr) || die("proxy connect to $host:$port failed: $!"); my($peer_port, $peer_addr) = (*$self->{ssl_peer_port}, *$self->{ssl_peer_addr}); $peer_port || die("no peer port given"); $peer_addr || die("no peer addr given"); my $connect_string; if ($ENV{"HTTPS_PROXY_USERNAME"} || $ENV{"HTTPS_PROXY_PASSWORD"}) { my $user = $ENV{"HTTPS_PROXY_USERNAME"}; my $pass = $ENV{"HTTPS_PROXY_PASSWORD"}; my $credentials = encode_base64("$user:$pass", ""); $connect_string = join($CRLF, "CONNECT $peer_addr:$peer_port HTTP/1.0", "Proxy-authorization: Basic $credentials" ); }else{ $connect_string = "CONNECT $peer_addr:$peer_port HTTP/1.0"; } $connect_string .= $CRLF; if($lwp_object && $lwp_object->agent) { $connect_string .= "User-Agent: ".$lwp_object->agent.$CRLF; } $connect_string .= $CRLF; $self->SUPER::send($connect_string); my $header; my $n = $self->SUPER::sysread($header, 8192); if($header =~ /HTTP\/\d+\.\d+\s+200\s+/is) { $conn_ok = 1; } unless ($conn_ok) { die("PROXY ERROR HEADER, could be non-SSL URL:\n$header"); } $conn_ok; } # code adapted from LWP::UserAgent, with $ua->env_proxy API sub proxy { # don't iterate through %ENV for speed my $proxy_server; for ('HTTPS_PROXY', 'https_proxy') { $proxy_server = $ENV{$_}; last if $proxy_server; } return unless $proxy_server; $proxy_server =~ s|^https?://||i; $proxy_server; } sub configure_certs { my $self = shift; my $ctx = *$self->{ssl_ctx}; my $count = 0; for ('HTTPS_PKCS12_FILE', 'HTTPS_CERT_FILE', 'HTTPS_KEY_FILE') { my $file = $ENV{$_}; if($file) { (-e $file) or die("$file file does not exist: $!"); $count++; if (/PKCS12/) { $count++; $ctx->use_pkcs12_file($file ,$ENV{'HTTPS_PKCS12_PASSWORD'}) || die("failed to load $file: $!"); last; } elsif (/CERT/) { $ctx->use_certificate_file($file ,1) || die("failed to load $file: $!"); } elsif (/KEY/) { $ctx->use_PrivateKey_file($file, 1) || die("failed to load $file: $!"); } else { die("setting $_ not supported"); } } } # if both configs are set, then verify them if (($count == 2)) { if (! $ctx->check_private_key) { die("Private key and certificate do not match"); } } $count; # number of successful cert loads/checks } 1;