1 package Net::SSLeay::Handle;
13 Net::SSLeay::Handle - Perl module that lets SSL (HTTPS) sockets be
14 handled as standard file handles.
18 use Net::SSLeay::Handle qw/shutdown/;
19 my ($host, $port) = ("localhost", 443);
21 tie(*SSL, "Net::SSLeay::Handle", $host, $port);
23 print SSL "GET / HTTP/1.0\r\n";
30 Net::SSLeay::Handle allows you to request and receive HTTPS web pages
31 using "old-fashion" file handles as in:
33 print SSL "GET / HTTP/1.0\r\n";
39 If you export the shutdown routine, then the only extra code that
40 you need to add to your program is the tie function as in:
43 if ($scheme eq "https") {
44 tie(*S2, "Net::SSLeay::Handle", $host, $port);
47 $socket = Net::SSLeay::Handle->make_socket($host, $port);
49 print $socket $request_headers;
54 use vars qw(@ISA @EXPORT_OK $VERSION);
56 @EXPORT_OK = qw(shutdown);
59 my $Initialized; #-- only _initialize() once
60 my $Debug = 0; #-- pretty hokey
61 my %Glob_Ref; #-- used to make unique \*S names for versions < 5.6
63 #== Tie Handle Methods ========================================================
65 # see perldoc perltie for details.
67 #==============================================================================
70 my ($class, $socket, $port) = @_;
71 $Debug > 10 and print "TIEHANDLE(@{[join ', ', @_]})\n";
73 ref $socket eq "GLOB" or $socket = $class->make_socket($socket, $port);
75 $class->_initialize();
77 my $ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!");
78 my $ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!");
80 my $fileno = fileno($socket);
82 Net::SSLeay::set_fd($ssl, $fileno); # Must use fileno
84 my $resp = Net::SSLeay::connect($ssl);
86 $Debug and print "Cipher '" . Net::SSLeay::get_cipher($ssl) . "'\n";
101 my $ssl = _get_ssl($self);
104 defined $msg or last;
105 $resp = Net::SSLeay::write($ssl, $msg) or last;
112 my $ssl = _get_ssl($self);
115 while (my $line = Net::SSLeay::ssl_read_until($ssl)) {
120 my $line = Net::SSLeay::ssl_read_until($ssl);
121 return $line ? $line : undef;
126 my ($self, $buf, $len, $offset) = \ (@_);
127 my $ssl = _get_ssl($$self);
129 return length($$buf = Net::SSLeay::ssl_read_all($ssl, $$len));
131 defined(my $read = Net::SSLeay::ssl_read_all($ssl, $$len))
134 my $buf_len = length($$buf);
135 $$offset > $buf_len and $$buf .= chr(0) x ($$offset - $buf_len);
136 substr($$buf, $$offset) = $read;
137 return length($read);
142 my ($buf, $len, $offset) = @_;
143 $offset = 0 unless defined $offset;
145 # Return number of characters written.
146 my $ssl = $self->_get_ssl();
147 return $len if Net::SSLeay::write($ssl, substr($buf, $offset, $len));
153 my $fileno = $self->{fileno};
154 $Debug > 10 and print "close($fileno)\n";
155 Net::SSLeay::free ($self->{ssl});
156 Net::SSLeay::CTX_free ($self->{ctx});
157 close $self->{socket};
160 sub FILENO { $_[0]->{fileno} }
169 shutdown(\*SOCKET, $mode)
171 Calls to the main shutdown() don't work with tied sockets created with this
172 module. This shutdown should be able to distinquish between tied and untied
173 sockets and do the right thing.
178 my ($obj, @params) = @_;
180 my $socket = UNIVERSAL::isa($obj, 'Net::SSLeay::Handle') ?
181 $obj->{socket} : $obj;
182 return shutdown($socket, @params);
187 my $debug = Net::SSLeay::Handle->debug()
188 Net::SSLeay::Handle->debug(1)
190 Get/set debuging mode. Always returns the debug value before the function call.
191 if an additional argument is given the debug option will be set to this value.
196 my ($class, $debug) = @_;
197 my $old_debug = $Debug;
198 @_ >1 and $Debug = $debug || 0;
202 #=== Internal Methods =========================================================
206 my $sock = Net::SSLeay::Handle->make_socket($host, $port);
208 Creates a socket that is connected to $post using $port. It uses
209 $Net::SSLeay::proxyhost and proxyport if set and authentificates itself against
210 this proxy depending on $Net::SSLeay::proxyauth. It also turns autoflush on for
216 my ($class, $host, $port) = @_;
217 $Debug > 10 and print "_make_socket(@{[join ', ', @_]})\n";
218 $host ||= 'localhost';
221 my $phost = $Net::SSLeay::proxyhost;
222 my $pport = $Net::SSLeay::proxyhost ? $Net::SSLeay::proxyport : $port;
224 my $dest_ip = gethostbyname($phost || $host);
225 my $host_params = sockaddr_in($pport, $dest_ip);
226 my $socket = $^V ? undef : $class->_glob_ref("$host:$port");
228 socket($socket, &PF_INET(), &SOCK_STREAM(), 0) or die "socket: $!";
229 connect($socket, $host_params) or die "connect: $!";
231 my $old_select = select($socket); $| = 1; select($old_select);
233 my $auth = $Net::SSLeay::proxyauth;
234 my $CRLF = $Net::SSLeay::CRLF;
235 print $socket "CONNECT $host:$port HTTP/1.0$auth$CRLF$CRLF";
236 my $line = <$socket>;
245 #--- _glob_ref($strings) ------------------------------------------------------
247 # Create a unique namespace name and return a glob ref to it. Would be great
248 # to use the fileno but need this before we get back the fileno.
249 # NEED TO LOCK THIS ROUTINE IF USING THREADS. (but it is only used for
251 #------------------------------------------------------------------------------
255 my $preamb = join("", @_) || "_glob_ref";
256 my $num = ++$Glob_Ref{$preamb};
257 my $name = "$preamb:$num";
259 my $glob_ref = \*$name;
263 print "GLOB_REF $preamb\n";
264 while (my ($k, $v) = each %Glob_Ref) {print "$k = $v\n"}
272 $Initialized++ and return;
273 Net::SSLeay::load_error_strings();
274 Net::SSLeay::SSLeay_add_ssl_algorithms();
275 Net::SSLeay::randomize();
279 my $host = $Net::SSLeay::proxyhost;
280 my $port = $Net::SSLeay::proxyport;
281 my $auth = $Net::SSLeay::proxyauth;
284 #--- _get_self($socket) -------------------------------------------------------
285 # Returns a hash containing attributes for $socket (= \*SOMETHING) based
286 # on fileno($socket). Will return undef if $socket was not created here.
287 #------------------------------------------------------------------------------
289 sub _get_self { return $_[0]; }
291 #--- _get_ssl($socket) --------------------------------------------------------
292 # Returns a the "ssl" attribute for $socket (= \*SOMETHING) based
293 # on fileno($socket). Will cause a warning and return undef if $socket was not
295 #------------------------------------------------------------------------------
305 =head2 USING EXISTING SOCKETS
307 One of the motivations for writing this module was to avoid
308 duplicating socket creation code (which is mostly error handling).
309 The calls to tie() above where it is passed a $host and $port is
310 provided for convenience testing. If you already have a socket
311 connected to the right host and port, S1, then you can do something
315 if ($scheme eq "https") {
316 tie(*S2, "Net::SSLeay::Handle", $socket);
319 my $last_sel = select($socket); $| = 1; select($last_sel);
320 print $socket $request_headers;
323 Note: As far as I know you must be careful with the globs in the tie()
324 function. The first parameter must be a glob (*SOMETHING) and the
325 last parameter must be a reference to a glob (\*SOMETHING_ELSE) or a
326 scaler that was assigned to a reference to a glob (as in the example
329 Also, the two globs must be different. When I tried to use the same
330 glob, I got a core dump.
336 You can export the shutdown() function.
338 It is suggested that you do export shutdown() or use the fully
339 qualified Net::SSLeay::Handle::shutdown() function to shutdown SSL
340 sockets. It should be smart enough to distinguish between SSL and
341 non-SSL sockets and do the right thing.
345 use Net::SSLeay::Handle qw/shutdown/;
346 my ($host, $port) = ("localhost", 443);
348 tie(*SSL, "Net::SSLeay::Handle", $host, $port);
350 print SSL "GET / HTTP/1.0\r\n";
357 Better error handling. Callback routine?
361 Tying to a file handle is a little tricky (for me at least).
363 The first parameter to tie() must be a glob (*SOMETHING) and the last
364 parameter must be a reference to a glob (\*SOMETHING_ELSE) or a scaler
365 that was assigned to a reference to a glob ($s = \*SOMETHING_ELSE).
366 Also, the two globs must be different. When I tried to use the same
367 glob, I got a core dump.
369 I was able to associate attributes to globs created by this module
370 (like *SSL above) by making a hash of hashes keyed by the file head1.
372 Support for old perls may not be 100%. If in trouble try 5.6.0 or
377 Please see Net-SSLeay-Handle-0.50/Changes file.
381 If you let this module construct sockets for you with Perl versions
382 below v.5.6 then there is a slight memory leak. Other upgrade your
383 Perl, or create the sockets yourself. The leak was created to let
384 these older versions of Perl access more than one Handle at a time.
388 Jim Bowlin jbowlin@linklint.org
392 Net::SSLeay, perl(1), http://openssl.org/