| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Net::SSL; |
|
2
|
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
36858
|
use strict; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
56
|
|
|
4
|
2
|
|
|
2
|
|
1811
|
use MIME::Base64; |
|
|
2
|
|
|
|
|
1825
|
|
|
|
2
|
|
|
|
|
133
|
|
|
5
|
2
|
|
|
2
|
|
2518
|
use Socket; |
|
|
2
|
|
|
|
|
11734
|
|
|
|
2
|
|
|
|
|
1340
|
|
|
6
|
2
|
|
|
2
|
|
23
|
use Carp; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
136
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
2
|
|
|
2
|
|
11
|
use vars qw(@ISA $VERSION $NEW_ARGS); |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
14690
|
|
|
9
|
|
|
|
|
|
|
$VERSION = '2.86'; |
|
10
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
require IO::Socket; |
|
13
|
|
|
|
|
|
|
@ISA=qw(IO::Socket::INET); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
my %REAL; # private to this package only |
|
16
|
|
|
|
|
|
|
my $DEFAULT_VERSION = '23'; |
|
17
|
|
|
|
|
|
|
my $CRLF = "\015\012"; |
|
18
|
|
|
|
|
|
|
my $SEND_USERAGENT_TO_PROXY = 0; |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
require Crypt::SSLeay; |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub _default_context { |
|
23
|
1
|
|
|
1
|
|
621
|
require Crypt::SSLeay::MainContext; |
|
24
|
1
|
|
|
|
|
6
|
Crypt::SSLeay::MainContext::main_ctx(@_); |
|
25
|
|
|
|
|
|
|
} |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub _alarm_set { |
|
28
|
0
|
0
|
0
|
0
|
|
0
|
return if $^O eq 'MSWin32' or $^O eq 'NetWare'; |
|
29
|
0
|
|
|
|
|
0
|
alarm(shift); |
|
30
|
|
|
|
|
|
|
} |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub new { |
|
33
|
1
|
|
|
1
|
1
|
110
|
my($class, %arg) = @_; |
|
34
|
1
|
|
|
|
|
3
|
local $NEW_ARGS = \%arg; |
|
35
|
1
|
|
|
|
|
19
|
$class->SUPER::new(%arg); |
|
36
|
|
|
|
|
|
|
} |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub DESTROY { |
|
39
|
1
|
|
|
1
|
|
2
|
my $self = shift; |
|
40
|
1
|
|
|
|
|
4
|
delete $REAL{$self}; |
|
41
|
1
|
|
|
|
|
2
|
local $@; |
|
42
|
1
|
|
|
|
|
2
|
eval { $self->SUPER::DESTROY; }; |
|
|
1
|
|
|
|
|
13
|
|
|
43
|
|
|
|
|
|
|
} |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub configure { |
|
46
|
1
|
|
|
1
|
1
|
198
|
my($self, $arg) = @_; |
|
47
|
1
|
|
33
|
|
|
16
|
my $ssl_version = delete $arg->{SSL_Version} || |
|
48
|
|
|
|
|
|
|
$ENV{HTTPS_VERSION} || $DEFAULT_VERSION; |
|
49
|
1
|
|
50
|
|
|
11
|
my $ssl_debug = delete $arg->{SSL_Debug} || $ENV{HTTPS_DEBUG} || 0; |
|
50
|
|
|
|
|
|
|
|
|
51
|
1
|
|
33
|
|
|
7
|
my $ctx = delete $arg->{SSL_Context} || _default_context($ssl_version); |
|
52
|
|
|
|
|
|
|
|
|
53
|
1
|
|
|
|
|
4
|
*$self->{ssl_ctx} = $ctx; |
|
54
|
1
|
|
|
|
|
4
|
*$self->{ssl_version} = $ssl_version; |
|
55
|
1
|
|
|
|
|
3
|
*$self->{ssl_debug} = $ssl_debug; |
|
56
|
1
|
|
|
|
|
3
|
*$self->{ssl_arg} = $arg; |
|
57
|
1
|
|
|
|
|
4
|
*$self->{ssl_peer_addr} = $arg->{PeerAddr}; |
|
58
|
1
|
|
|
|
|
3
|
*$self->{ssl_peer_port} = $arg->{PeerPort}; |
|
59
|
1
|
|
|
|
|
3
|
*$self->{ssl_new_arg} = $NEW_ARGS; |
|
60
|
1
|
|
|
|
|
3
|
*$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
|
1
|
50
|
|
|
|
6
|
if (my $proxy = $self->proxy) { |
|
68
|
0
|
|
|
|
|
0
|
($arg->{PeerAddr}, $arg->{PeerPort}) = split(':',$proxy); |
|
69
|
0
|
0
|
|
|
|
0
|
$arg->{PeerPort} || croak("no port given for proxy server $proxy"); |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
|
|
72
|
1
|
|
|
|
|
14
|
$self->SUPER::configure($arg); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# override to make sure there is really a timeout |
|
76
|
|
|
|
|
|
|
sub timeout { |
|
77
|
0
|
0
|
|
0
|
1
|
0
|
shift->SUPER::timeout || 60; |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub blocking { |
|
81
|
2
|
|
|
2
|
1
|
3010
|
my $self = shift; |
|
82
|
2
|
|
|
|
|
13
|
$self->SUPER::blocking(@_); |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub connect { |
|
86
|
1
|
|
|
1
|
1
|
224
|
my $self = shift; |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# configure certs on connect() time, so we can throw an undef |
|
89
|
|
|
|
|
|
|
# and have LWP understand the error |
|
90
|
1
|
|
|
|
|
2
|
eval { $self->configure_certs() }; |
|
|
1
|
|
|
|
|
5
|
|
|
91
|
1
|
50
|
|
|
|
4
|
if($@) { |
|
92
|
0
|
|
|
|
|
0
|
$@ = "configure certs failed: $@; $!"; |
|
93
|
0
|
|
|
|
|
0
|
$self->die_with_error($@); |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# finished, update set_verify status |
|
97
|
1
|
50
|
|
|
|
13
|
if(my $rv = *$self->{ssl_ctx}->set_verify()) { |
|
98
|
0
|
|
|
|
|
0
|
*$self->{ssl_peer_verify} = $rv; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
1
|
50
|
|
|
|
3
|
if ($self->proxy) { |
|
102
|
|
|
|
|
|
|
# don't die() in connect, just return undef and set $@ |
|
103
|
0
|
|
|
|
|
0
|
my $proxy_connect = eval { $self->proxy_connect_helper(@_) }; |
|
|
0
|
|
|
|
|
0
|
|
|
104
|
0
|
0
|
0
|
|
|
0
|
if(! $proxy_connect || $@) { |
|
105
|
0
|
|
|
|
|
0
|
$@ = "proxy connect failed: $@; $!"; |
|
106
|
0
|
|
|
|
|
0
|
croak($@); |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
else { |
|
110
|
1
|
50
|
|
|
|
5
|
*$self->{io_socket_peername}=@_ == 1 ? $_[0] : IO::Socket::sockaddr_in(@_); |
|
111
|
1
|
50
|
|
|
|
9
|
if(!$self->SUPER::connect(@_)) { |
|
112
|
|
|
|
|
|
|
# better to die than return here |
|
113
|
1
|
|
|
|
|
23
|
$@ = "Connect failed: $@; $!"; |
|
114
|
1
|
|
|
|
|
408
|
croak($@); |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
0
|
|
0
|
|
|
0
|
my $debug = *$self->{ssl_debug} || 0; |
|
119
|
0
|
|
|
|
|
0
|
my $ssl = Crypt::SSLeay::Conn->new(*$self->{ssl_ctx}, $debug, $self); |
|
120
|
0
|
|
|
|
|
0
|
my $arg = *$self->{ssl_arg}; |
|
121
|
0
|
|
|
|
|
0
|
my $new_arg = *$self->{ssl_new_arg}; |
|
122
|
0
|
|
|
|
|
0
|
$arg->{SSL_Debug} = $debug; |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# setup SNI if available |
|
125
|
0
|
0
|
|
|
|
0
|
$ssl->can("set_tlsext_host_name") and |
|
126
|
|
|
|
|
|
|
$ssl->set_tlsext_host_name(*$self->{ssl_peer_addr}); |
|
127
|
|
|
|
|
|
|
|
|
128
|
0
|
|
|
|
|
0
|
eval { |
|
129
|
0
|
|
|
0
|
|
0
|
local $SIG{ALRM} = sub { $self->die_with_error("SSL connect timeout") }; |
|
|
0
|
|
|
|
|
0
|
|
|
130
|
|
|
|
|
|
|
# timeout / 2 because we have 3 possible connects here |
|
131
|
0
|
|
|
|
|
0
|
_alarm_set($self->timeout / 2); |
|
132
|
|
|
|
|
|
|
|
|
133
|
0
|
|
|
|
|
0
|
my $rv; |
|
134
|
|
|
|
|
|
|
{ |
|
135
|
0
|
|
|
|
|
0
|
local $SIG{PIPE} = \¨ |
|
|
0
|
|
|
|
|
0
|
|
|
136
|
0
|
|
|
|
|
0
|
$rv = eval { $ssl->connect; }; |
|
|
0
|
|
|
|
|
0
|
|
|
137
|
|
|
|
|
|
|
} |
|
138
|
0
|
0
|
0
|
|
|
0
|
if (not defined $rv or $rv <= 0) { |
|
139
|
0
|
|
|
|
|
0
|
_alarm_set(0); |
|
140
|
0
|
|
|
|
|
0
|
$ssl = undef; |
|
141
|
|
|
|
|
|
|
# See RT #59312 |
|
142
|
0
|
|
|
|
|
0
|
my %args = (%$arg, %$new_arg); |
|
143
|
0
|
0
|
|
|
|
0
|
if(*$self->{ssl_version} == 23) { |
|
|
|
0
|
|
|
|
|
|
|
144
|
0
|
|
|
|
|
0
|
$args{SSL_Version} = 3; |
|
145
|
|
|
|
|
|
|
# the new connect might itself be overridden with a REAL SSL |
|
146
|
0
|
|
|
|
|
0
|
my $new_ssl = Net::SSL->new(%args); |
|
147
|
0
|
|
0
|
|
|
0
|
$REAL{$self} = $REAL{$new_ssl} || $new_ssl; |
|
148
|
0
|
|
|
|
|
0
|
return $REAL{$self}; |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
elsif(*$self->{ssl_version} == 3) { |
|
151
|
|
|
|
|
|
|
# $self->die_with_error("SSL negotiation failed"); |
|
152
|
0
|
|
|
|
|
0
|
$args{SSL_Version} = 2; |
|
153
|
0
|
|
|
|
|
0
|
my $new_ssl = Net::SSL->new(%args); |
|
154
|
0
|
|
|
|
|
0
|
$REAL{$self} = $new_ssl; |
|
155
|
0
|
|
|
|
|
0
|
return $new_ssl; |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
else { |
|
158
|
|
|
|
|
|
|
# don't die, but do set $@, and return undef |
|
159
|
0
|
|
|
|
|
0
|
eval { $self->die_with_error("SSL negotiation failed") }; |
|
|
0
|
|
|
|
|
0
|
|
|
160
|
0
|
|
|
|
|
0
|
croak($@); |
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
} |
|
163
|
0
|
|
|
|
|
0
|
_alarm_set(0); |
|
164
|
|
|
|
|
|
|
}; |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# odd error in eval {} block, maybe alarm outside the evals |
|
167
|
0
|
0
|
|
|
|
0
|
if($@) { |
|
168
|
0
|
|
|
|
|
0
|
$@ = "$@; $!"; |
|
169
|
0
|
|
|
|
|
0
|
croak($@); |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# successful SSL connection gets stored |
|
173
|
0
|
|
|
|
|
0
|
*$self->{ssl_ssl} = $ssl; |
|
174
|
0
|
|
|
|
|
0
|
$self; |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# Delegate these calls to the Crypt::SSLeay::Conn object |
|
178
|
|
|
|
|
|
|
sub get_peer_certificate { |
|
179
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
180
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
181
|
0
|
|
|
|
|
0
|
*$self->{ssl_ssl}->get_peer_certificate(@_); |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub get_peer_verify { |
|
185
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
186
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
187
|
0
|
|
|
|
|
0
|
*$self->{ssl_peer_verify}; |
|
188
|
|
|
|
|
|
|
} |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub get_shared_ciphers { |
|
191
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
192
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
193
|
0
|
|
|
|
|
0
|
*$self->{ssl_ssl}->get_shared_ciphers(@_); |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub get_cipher { |
|
197
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
198
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
199
|
0
|
|
|
|
|
0
|
*$self->{ssl_ssl}->get_cipher(@_); |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub pending { |
|
203
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
204
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
205
|
0
|
|
|
|
|
0
|
*$self->{ssl_ssl}->pending(@_); |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub ssl_context { |
|
209
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
210
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
211
|
0
|
|
|
|
|
0
|
*$self->{ssl_ctx}; |
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub die_with_error { |
|
215
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
|
216
|
0
|
|
|
|
|
0
|
my $reason=shift; |
|
217
|
|
|
|
|
|
|
|
|
218
|
0
|
|
|
|
|
0
|
my @err; |
|
219
|
0
|
|
|
|
|
0
|
while(my $err=Crypt::SSLeay::Err::get_error_string()) { |
|
220
|
0
|
|
|
|
|
0
|
push @err, $err; |
|
221
|
|
|
|
|
|
|
} |
|
222
|
0
|
|
|
|
|
0
|
croak("$reason: " . join( ' | ', @err )); |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub read { |
|
226
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
227
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
228
|
|
|
|
|
|
|
|
|
229
|
0
|
|
|
|
|
0
|
local $SIG{__DIE__} = \&Carp::confess; |
|
230
|
0
|
|
|
0
|
|
0
|
local $SIG{ALRM} = sub { $self->die_with_error("SSL read timeout") }; |
|
|
0
|
|
|
|
|
0
|
|
|
231
|
|
|
|
|
|
|
|
|
232
|
0
|
|
|
|
|
0
|
_alarm_set($self->timeout); |
|
233
|
0
|
|
|
|
|
0
|
my $n = *$self->{ssl_ssl}->read(@_); |
|
234
|
0
|
|
|
|
|
0
|
_alarm_set(0); |
|
235
|
0
|
0
|
|
|
|
0
|
$self->die_with_error("read failed") if !defined $n; |
|
236
|
|
|
|
|
|
|
|
|
237
|
0
|
|
|
|
|
0
|
$n; |
|
238
|
|
|
|
|
|
|
} |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub write { |
|
241
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
242
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
243
|
0
|
|
|
|
|
0
|
my $n = *$self->{ssl_ssl}->write(@_); |
|
244
|
0
|
0
|
|
|
|
0
|
$self->die_with_error("write failed") if !defined $n; |
|
245
|
0
|
|
|
|
|
0
|
$n; |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
*sysread = \&read; |
|
249
|
|
|
|
|
|
|
*syswrite = \&write; |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub print { |
|
252
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
253
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
254
|
|
|
|
|
|
|
# should we care about $, and $\?? |
|
255
|
|
|
|
|
|
|
# I think it is too expensive... |
|
256
|
0
|
|
|
|
|
0
|
$self->write(join("", @_)); |
|
257
|
|
|
|
|
|
|
} |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub printf { |
|
260
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
261
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
262
|
0
|
|
|
|
|
0
|
my $fmt = shift; |
|
263
|
0
|
|
|
|
|
0
|
$self->write(sprintf($fmt, @_)); |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
sub getchunk { |
|
267
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
268
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
269
|
0
|
|
|
|
|
0
|
my $buf = ''; # warnings |
|
270
|
0
|
|
|
|
|
0
|
my $n = $self->read($buf, 32768); |
|
271
|
0
|
0
|
|
|
|
0
|
return unless defined $n; |
|
272
|
0
|
|
|
|
|
0
|
$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. |
|
277
|
|
|
|
|
|
|
sub getline { |
|
278
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
279
|
0
|
|
0
|
|
|
0
|
$self = $REAL{$self} || $self; |
|
280
|
0
|
|
|
|
|
0
|
my $val=""; |
|
281
|
0
|
|
|
|
|
0
|
my $buf; |
|
282
|
0
|
|
|
|
|
0
|
do { |
|
283
|
0
|
|
|
|
|
0
|
$self->SUPER::recv($buf, 1); |
|
284
|
0
|
|
|
|
|
0
|
$val .= $buf; |
|
285
|
|
|
|
|
|
|
} until ($buf eq "\n"); |
|
286
|
|
|
|
|
|
|
|
|
287
|
0
|
|
|
|
|
0
|
$val; |
|
288
|
|
|
|
|
|
|
} |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# XXX: no way to disable <$sock>?? (tied handle perhaps?) |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
sub get_lwp_object { |
|
293
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
294
|
|
|
|
|
|
|
|
|
295
|
0
|
|
|
|
|
0
|
my $lwp_object; |
|
296
|
0
|
|
|
|
|
0
|
my $i = 0; |
|
297
|
0
|
|
|
|
|
0
|
while(1) { |
|
298
|
|
|
|
|
|
|
package DB; |
|
299
|
0
|
|
|
|
|
0
|
my @stack = caller($i++); |
|
300
|
0
|
0
|
|
|
|
0
|
last unless @stack; |
|
301
|
0
|
|
|
|
|
0
|
my @stack_args = @DB::args; |
|
302
|
0
|
|
0
|
|
|
0
|
my $stack_object = $stack_args[0] || next; |
|
303
|
0
|
0
|
0
|
|
|
0
|
return $stack_object |
|
304
|
|
|
|
|
|
|
if ref($stack_object) |
|
305
|
|
|
|
|
|
|
and $stack_object->isa('LWP::UserAgent'); |
|
306
|
|
|
|
|
|
|
} |
|
307
|
0
|
|
|
|
|
0
|
return undef; |
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub send_useragent_to_proxy { |
|
311
|
0
|
0
|
|
0
|
1
|
0
|
if (my $val = shift) { |
|
312
|
0
|
|
|
|
|
0
|
$SEND_USERAGENT_TO_PROXY = $val; |
|
313
|
|
|
|
|
|
|
} |
|
314
|
0
|
|
|
|
|
0
|
return $SEND_USERAGENT_TO_PROXY; |
|
315
|
|
|
|
|
|
|
} |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
sub proxy_connect_helper { |
|
318
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
319
|
|
|
|
|
|
|
|
|
320
|
0
|
|
|
|
|
0
|
my $proxy = $self->proxy; |
|
321
|
0
|
|
|
|
|
0
|
my ($proxy_host, $proxy_port) = split(':',$proxy); |
|
322
|
0
|
0
|
|
|
|
0
|
$proxy_port || croak("no port given for proxy server $proxy"); |
|
323
|
|
|
|
|
|
|
|
|
324
|
0
|
|
|
|
|
0
|
my $proxy_addr = gethostbyname($proxy_host); |
|
325
|
0
|
0
|
|
|
|
0
|
$proxy_addr || croak("can't resolve proxy server name: $proxy_host, $!"); |
|
326
|
|
|
|
|
|
|
|
|
327
|
0
|
|
|
|
|
0
|
my($peer_port, $peer_addr) = (*$self->{ssl_peer_port}, *$self->{ssl_peer_addr}); |
|
328
|
0
|
0
|
|
|
|
0
|
$peer_addr || croak("no peer addr given"); |
|
329
|
0
|
0
|
|
|
|
0
|
$peer_port || croak("no peer port given"); |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# see if the proxy should be bypassed |
|
332
|
0
|
|
0
|
|
|
0
|
my @no_proxy = split( /\s*,\s*/, $ENV{NO_PROXY} || $ENV{no_proxy} || ''); |
|
333
|
0
|
|
|
|
|
0
|
my $is_proxied = 1; |
|
334
|
0
|
|
|
|
|
0
|
my $domain; |
|
335
|
0
|
|
|
|
|
0
|
for $domain (@no_proxy) { |
|
336
|
0
|
0
|
|
|
|
0
|
if ($peer_addr =~ /\Q$domain\E$/) { |
|
337
|
0
|
|
|
|
|
0
|
$is_proxied = 0; |
|
338
|
0
|
|
|
|
|
0
|
last; |
|
339
|
|
|
|
|
|
|
} |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
|
|
342
|
0
|
0
|
|
|
|
0
|
if ($is_proxied) { |
|
343
|
0
|
0
|
|
|
|
0
|
$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
|
0
|
|
|
|
|
0
|
my $peer_addr_packed = gethostbyname($peer_addr); |
|
349
|
0
|
0
|
|
|
|
0
|
$self->SUPER::connect($peer_port, $peer_addr_packed) |
|
350
|
|
|
|
|
|
|
|| croak("proxy bypass to $peer_addr:$peer_addr failed: $!"); |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
|
|
353
|
0
|
|
|
|
|
0
|
my $connect_string; |
|
354
|
0
|
0
|
0
|
|
|
0
|
if ($ENV{"HTTPS_PROXY_USERNAME"} || $ENV{"HTTPS_PROXY_PASSWORD"}) { |
|
355
|
0
|
|
|
|
|
0
|
my $user = $ENV{"HTTPS_PROXY_USERNAME"}; |
|
356
|
0
|
|
|
|
|
0
|
my $pass = $ENV{"HTTPS_PROXY_PASSWORD"}; |
|
357
|
|
|
|
|
|
|
|
|
358
|
0
|
|
|
|
|
0
|
my $credentials = encode_base64("$user:$pass", ""); |
|
359
|
0
|
|
|
|
|
0
|
$connect_string = join($CRLF, |
|
360
|
|
|
|
|
|
|
"CONNECT $peer_addr:$peer_port HTTP/1.0", |
|
361
|
|
|
|
|
|
|
"Proxy-authorization: Basic $credentials" |
|
362
|
|
|
|
|
|
|
); |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
else { |
|
365
|
0
|
|
|
|
|
0
|
$connect_string = "CONNECT $peer_addr:$peer_port HTTP/1.0"; |
|
366
|
|
|
|
|
|
|
} |
|
367
|
0
|
|
|
|
|
0
|
$connect_string .= $CRLF; |
|
368
|
|
|
|
|
|
|
|
|
369
|
0
|
0
|
|
|
|
0
|
if (send_useragent_to_proxy()) { |
|
370
|
0
|
|
|
|
|
0
|
my $lwp_object = $self->get_lwp_object; |
|
371
|
0
|
0
|
0
|
|
|
0
|
if($lwp_object && $lwp_object->agent) { |
|
372
|
0
|
|
|
|
|
0
|
$connect_string .= "User-Agent: ".$lwp_object->agent.$CRLF; |
|
373
|
|
|
|
|
|
|
} |
|
374
|
|
|
|
|
|
|
} |
|
375
|
|
|
|
|
|
|
|
|
376
|
0
|
|
|
|
|
0
|
$connect_string .= $CRLF; |
|
377
|
0
|
|
|
|
|
0
|
$self->SUPER::send($connect_string); |
|
378
|
|
|
|
|
|
|
|
|
379
|
0
|
|
|
|
|
0
|
my $timeout; |
|
380
|
0
|
|
|
|
|
0
|
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
|
0
|
|
|
|
|
0
|
while ($header !~ m{HTTP/[0-9][.][0-9]\s+200\s+.*$CRLF$CRLF}s) { |
|
389
|
0
|
0
|
|
|
|
0
|
$timeout = $self->timeout(5) unless length $header; |
|
390
|
0
|
|
|
|
|
0
|
my $n = $self->SUPER::sysread($header, 8192, length $header); |
|
391
|
0
|
0
|
|
|
|
0
|
last if $n <= 0; |
|
392
|
|
|
|
|
|
|
} |
|
393
|
|
|
|
|
|
|
|
|
394
|
0
|
0
|
|
|
|
0
|
$self->timeout($timeout) if defined $timeout; |
|
395
|
0
|
0
|
|
|
|
0
|
my $conn_ok = ($header =~ m{HTTP/[0-9]+[.][0-9]+\s+200\s+}is) ? 1 : 0; |
|
396
|
|
|
|
|
|
|
|
|
397
|
0
|
0
|
|
|
|
0
|
if (not $conn_ok) { |
|
398
|
0
|
|
|
|
|
0
|
croak("PROXY ERROR HEADER, could be non-SSL URL:\n$header"); |
|
399
|
|
|
|
|
|
|
} |
|
400
|
|
|
|
|
|
|
|
|
401
|
0
|
|
|
|
|
0
|
$conn_ok; |
|
402
|
|
|
|
|
|
|
} |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# code adapted from LWP::UserAgent, with $ua->env_proxy API |
|
405
|
|
|
|
|
|
|
# see also RT #57836 |
|
406
|
|
|
|
|
|
|
sub proxy { |
|
407
|
2
|
|
|
2
|
1
|
5
|
my $self = shift; |
|
408
|
2
|
|
33
|
|
|
15
|
my $proxy_server = $ENV{HTTPS_PROXY} || $ENV{https_proxy}; |
|
409
|
2
|
50
|
|
|
|
14
|
return unless $proxy_server; |
|
410
|
|
|
|
|
|
|
|
|
411
|
0
|
|
|
|
|
0
|
my($peer_port, $peer_addr) = ( |
|
412
|
|
|
|
|
|
|
*$self->{ssl_peer_port}, |
|
413
|
|
|
|
|
|
|
*$self->{ssl_peer_addr} |
|
414
|
|
|
|
|
|
|
); |
|
415
|
0
|
0
|
|
|
|
0
|
$peer_addr || croak("no peer addr given"); |
|
416
|
0
|
0
|
|
|
|
0
|
$peer_port || croak("no peer port given"); |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
# see if the proxy should be bypassed |
|
419
|
0
|
|
0
|
|
|
0
|
my @no_proxy = split( /\s*,\s*/, |
|
420
|
|
|
|
|
|
|
$ENV{NO_PROXY} || $ENV{no_proxy} || '' |
|
421
|
|
|
|
|
|
|
); |
|
422
|
0
|
|
|
|
|
0
|
my $is_proxied = 1; |
|
423
|
0
|
|
|
|
|
0
|
for my $domain (@no_proxy) { |
|
424
|
0
|
0
|
|
|
|
0
|
if ($peer_addr =~ /\Q$domain\E\z/) { |
|
425
|
0
|
|
|
|
|
0
|
return; |
|
426
|
|
|
|
|
|
|
} |
|
427
|
|
|
|
|
|
|
} |
|
428
|
|
|
|
|
|
|
|
|
429
|
0
|
|
|
|
|
0
|
$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
|
0
|
|
|
|
|
0
|
$proxy_server =~ s|(:[1-9][0-9]{0,4})/\z|$1|; |
|
435
|
0
|
|
|
|
|
0
|
$proxy_server; |
|
436
|
|
|
|
|
|
|
} |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
sub configure_certs { |
|
439
|
1
|
|
|
1
|
1
|
2
|
my $self = shift; |
|
440
|
1
|
|
|
|
|
4
|
my $ctx = *$self->{ssl_ctx}; |
|
441
|
|
|
|
|
|
|
|
|
442
|
1
|
|
|
|
|
2
|
my $count = 0; |
|
443
|
1
|
|
|
|
|
3
|
for (qw(HTTPS_PKCS12_FILE HTTPS_CERT_FILE HTTPS_KEY_FILE)) { |
|
444
|
3
|
|
|
|
|
6
|
my $file = $ENV{$_}; |
|
445
|
3
|
50
|
|
|
|
10
|
if ($file) { |
|
446
|
0
|
0
|
|
|
|
0
|
(-e $file) or croak("$file file does not exist: $!"); |
|
447
|
0
|
0
|
|
|
|
0
|
(-r $file) or croak("$file file is not readable"); |
|
448
|
0
|
|
|
|
|
0
|
$count++; |
|
449
|
0
|
0
|
|
|
|
0
|
if (/PKCS12/) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
450
|
0
|
|
|
|
|
0
|
$count++; |
|
451
|
0
|
0
|
|
|
|
0
|
$ctx->use_pkcs12_file($file ,$ENV{'HTTPS_PKCS12_PASSWORD'}) || croak("failed to load $file: $!"); |
|
452
|
0
|
|
|
|
|
0
|
last; |
|
453
|
|
|
|
|
|
|
} |
|
454
|
|
|
|
|
|
|
elsif (/CERT/) { |
|
455
|
0
|
0
|
|
|
|
0
|
$ctx->use_certificate_file($file ,1) || croak("failed to load $file: $!"); |
|
456
|
|
|
|
|
|
|
} |
|
457
|
|
|
|
|
|
|
elsif (/KEY/) { |
|
458
|
0
|
0
|
|
|
|
0
|
$ctx->use_PrivateKey_file($file, 1) || croak("failed to load $file: $!"); |
|
459
|
|
|
|
|
|
|
} |
|
460
|
|
|
|
|
|
|
else { |
|
461
|
0
|
|
|
|
|
0
|
croak("setting $_ not supported"); |
|
462
|
|
|
|
|
|
|
} |
|
463
|
|
|
|
|
|
|
} |
|
464
|
|
|
|
|
|
|
} |
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
# if both configs are set, then verify them |
|
467
|
1
|
50
|
|
|
|
3
|
if ($count == 2) { |
|
468
|
0
|
0
|
|
|
|
0
|
if (! $ctx->check_private_key) { |
|
469
|
0
|
|
|
|
|
0
|
croak("Private key and certificate do not match"); |
|
470
|
|
|
|
|
|
|
} |
|
471
|
|
|
|
|
|
|
} |
|
472
|
|
|
|
|
|
|
|
|
473
|
1
|
|
|
|
|
3
|
$count; # number of successful cert loads/checks |
|
474
|
|
|
|
|
|
|
} |
|
475
|
|
|
|
|
|
|
|
|
476
|
0
|
|
|
0
|
1
|
|
sub accept { shift->_unimpl("accept") } |
|
477
|
0
|
|
|
0
|
1
|
|
sub getc { shift->_unimpl("getc") } |
|
478
|
0
|
|
|
0
|
1
|
|
sub ungetc { shift->_unimpl("ungetc") } |
|
479
|
0
|
|
|
0
|
1
|
|
sub getlines { shift->_unimpl("getlines"); } |
|
480
|
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
sub _unimpl { |
|
482
|
0
|
|
|
0
|
|
|
my($self, $meth) = @_; |
|
483
|
0
|
|
|
|
|
|
croak("$meth not implemented for Net::SSL sockets"); |
|
484
|
|
|
|
|
|
|
} |
|
485
|
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
1; |
|
487
|
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
__END__ |