141 lines
3.7 KiB
Perl
Raw Normal View History

#
# 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;