141 lines
3.7 KiB
Perl
141 lines
3.7 KiB
Perl
|
#
|
||
|
# Copyright (c) 2007 Michael Schroeder, Novell Inc.
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU General Public License version 2 as
|
||
|
# published by the Free Software Foundation.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with this program (see the file COPYING); if not, write to the
|
||
|
# Free Software Foundation, Inc.,
|
||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||
|
#
|
||
|
################################################################
|
||
|
#
|
||
|
# SSL Socket wrapper. Like Net::SSLeay::Handle, but can tie
|
||
|
# inplace and also supports servers. Plus, it uses the more useful
|
||
|
# Net::SSLeay::read instead of Net::SSLeay::ssl_read_all.
|
||
|
#
|
||
|
|
||
|
package BSSSL;
|
||
|
|
||
|
use Socket;
|
||
|
use Net::SSLeay;
|
||
|
|
||
|
use strict;
|
||
|
|
||
|
my $sslctx;
|
||
|
|
||
|
sub initctx {
|
||
|
my ($keyfile, $certfile) = @_;
|
||
|
Net::SSLeay::load_error_strings();
|
||
|
Net::SSLeay::SSLeay_add_ssl_algorithms();
|
||
|
Net::SSLeay::randomize();
|
||
|
$sslctx = Net::SSLeay::CTX_new() or die("CTX_new failed!\n");
|
||
|
Net::SSLeay::CTX_set_options($sslctx, &Net::SSLeay::OP_ALL);
|
||
|
if ($keyfile) {
|
||
|
Net::SSLeay::CTX_use_RSAPrivateKey_file($sslctx, $keyfile, &Net::SSLeay::FILETYPE_PEM) || die("RSAPrivateKey $keyfile failed\n");
|
||
|
}
|
||
|
if ($certfile) {
|
||
|
Net::SSLeay::CTX_use_certificate_file($sslctx, $certfile, &Net::SSLeay::FILETYPE_PEM) || die("certificate $keyfile failed\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sub freectx {
|
||
|
Net::SSLeay::CTX_free($sslctx);
|
||
|
undef $sslctx;
|
||
|
}
|
||
|
|
||
|
sub tossl {
|
||
|
local *S = $_[0];
|
||
|
tie(*S, 'BSSSL', @_);
|
||
|
}
|
||
|
|
||
|
sub TIEHANDLE {
|
||
|
my ($self, $socket, $keyfile, $certfile, $forceconnect) = @_;
|
||
|
|
||
|
initctx() unless $sslctx;
|
||
|
my $ssl = Net::SSLeay::new($sslctx) or die("SSL_new failed\n");
|
||
|
Net::SSLeay::set_fd($ssl, fileno($socket));
|
||
|
if ($keyfile) {
|
||
|
Net::SSLeay::use_RSAPrivateKey_file($ssl, $keyfile, &Net::SSLeay::FILETYPE_PEM) || die("RSAPrivateKey $keyfile failed\n");
|
||
|
}
|
||
|
if ($certfile) {
|
||
|
Net::SSLeay::use_certificate_file($ssl, $certfile, &Net::SSLeay::FILETYPE_PEM) || die("certificate $certfile failed\n");
|
||
|
}
|
||
|
if (defined($keyfile) && !$forceconnect) {
|
||
|
Net::SSLeay::accept($ssl) == 1 || die("SSL_accept\n");
|
||
|
} else {
|
||
|
Net::SSLeay::connect($ssl) || die("SSL_connect");
|
||
|
}
|
||
|
return bless [$ssl, $socket];
|
||
|
}
|
||
|
|
||
|
sub PRINT {
|
||
|
my $sslr = shift;
|
||
|
my $r = 0;
|
||
|
for my $msg (@_) {
|
||
|
next unless defined $msg;
|
||
|
$r = Net::SSLeay::write($sslr->[0], $msg) or last;
|
||
|
}
|
||
|
return $r;
|
||
|
}
|
||
|
|
||
|
sub READLINE {
|
||
|
my ($sslr) = @_;
|
||
|
return Net::SSLeay::ssl_read_until($sslr->[0]);
|
||
|
}
|
||
|
|
||
|
sub READ {
|
||
|
my ($sslr, undef, $len, $offset) = @_;
|
||
|
my $buf = \$_[1];
|
||
|
my $r = Net::SSLeay::read($sslr->[0], $len);
|
||
|
return undef unless defined $r;
|
||
|
return length($$buf = $r) unless defined $offset;
|
||
|
my $bl = length($$buf);
|
||
|
$$buf .= chr(0) x ($offset - $bl) if $offset > $bl;
|
||
|
substr($$buf, $offset) = $r;
|
||
|
return length($r);
|
||
|
}
|
||
|
|
||
|
sub WRITE {
|
||
|
my ($sslr, $buf, $len, $offset) = @_;
|
||
|
return $len unless $len;
|
||
|
return Net::SSLeay::write($sslr->[0], substr($buf, $offset || 0, $len)) ? $len : undef;
|
||
|
}
|
||
|
|
||
|
sub FILENO {
|
||
|
my ($sslr) = @_;
|
||
|
return Net::SSLeay::get_fd($sslr->[0]);
|
||
|
}
|
||
|
|
||
|
sub CLOSE {
|
||
|
my ($sslr) = @_;
|
||
|
if (tied($sslr->[1]) && tied($sslr->[1]) eq $sslr) {
|
||
|
untie($sslr->[1]);
|
||
|
close($sslr->[1]);
|
||
|
} else {
|
||
|
Net::SSLeay::free($sslr->[0]);
|
||
|
undef $sslr->[0];
|
||
|
}
|
||
|
undef $sslr->[1];
|
||
|
}
|
||
|
|
||
|
sub UNTIE {
|
||
|
my ($sslr) = @_;
|
||
|
Net::SSLeay::free($sslr->[0]);
|
||
|
undef $sslr->[0];
|
||
|
}
|
||
|
|
||
|
sub DESTROY {
|
||
|
my ($sslr) = @_;
|
||
|
UNTIE($sslr) if $sslr && $sslr->[0];
|
||
|
}
|
||
|
|
||
|
1;
|