IO-Socket-SSL

 view release on metacpan or  search on metacpan

lib/IO/Socket/SSL.pm  view on Meta::CPAN

    my $openssldir;

    sub default_ca {
	if (@_) {
	    # user defined default CA or reset
	    if ( @_ > 1 ) {
		%default_ca = @_;
		$ca_detected  = 0;
	    } elsif ( my $path = shift ) {
		%default_ca = $CHECK_SSL_PATH->($path);
		$ca_detected  = 0;
	    } else {
		$ca_detected = undef;
	    }
	}
	return %default_ca if defined $ca_detected;

	# SSLEAY_DIR was 5 up to OpenSSL 1.1, then switched to 4 and got
	# renamed to OPENSSL_DIR. Unfortunately it is not exported as constant
	# by Net::SSLeay so we use the fixed number.
	$openssldir ||=
	    Net::SSLeay::SSLeay_version(5) =~m{^OPENSSLDIR: "(.+)"$} ? $1 :
	    Net::SSLeay::SSLeay_version(4) =~m{^OPENSSLDIR: "(.+)"$} ? $1 :
	    'cannot-determine-openssldir-from-ssleay-version';

	# (re)detect according to openssl crypto/cryptlib.h
	my $dir = $ENV{SSL_CERT_DIR}
	    || ( $^O =~m{vms}i ? "SSLCERTS:":"$openssldir/certs" );
	if ( opendir(my $dh,$dir)) {
	    FILES: for my $f (  grep { m{^[a-f\d]{8}(\.\d+)?$} } readdir($dh) ) {
		open( my $fh,'<',"$dir/$f") or next;
		while (my $line = <$fh>) {
		    $line =~m{^-+BEGIN (X509 |TRUSTED |)CERTIFICATE-} or next;
		    $default_ca{SSL_ca_path} = $dir;
		    last FILES;
		}
	    }
	}
	my $file = $ENV{SSL_CERT_FILE}
	    || ( $^O =~m{vms}i ? "SSLCERTS:cert.pem":"$openssldir/cert.pem" );
	if ( open(my $fh,'<',$file)) {
	    while (my $line = <$fh>) {
		$line =~m{^-+BEGIN (X509 |TRUSTED |)CERTIFICATE-} or next;
		$default_ca{SSL_ca_file} = $file;
		last;
	    }
	}

	$default_ca{SSL_ca_file} = Mozilla::CA::SSL_ca_file() if ! %default_ca && do {
		local $SIG{__DIE__};
		eval { require Mozilla::CA; 1 };
	    };

	$ca_detected = 1;
	return %default_ca;
    }
}


# Export some stuff
# inet4|inet6|debug will be handled by myself, everything
# else will be handled the Exporter way
sub import {
    my $class = shift;

    my @export;
    foreach (@_) {
	if ( /^inet4$/i ) {
	    # explicitly fall back to inet4
	    @ISA = 'IO::Socket::INET';
	    @caller_force_inet4 = caller(); # save for warnings for 'inet6' case
	} elsif ( /^inet6$/i ) {
	    # check if we have already ipv6 as base
	    if ( ! UNIVERSAL::isa( $class, 'IO::Socket::INET6')
		and ! UNIVERSAL::isa( $class, 'IO::Socket::IP' )) {
		# either we don't support it or we disabled it by explicitly
		# loading it with 'inet4'. In this case re-enable but warn
		# because this is probably an error
		if ( CAN_IPV6 ) {
		    @ISA = ( CAN_IPV6 );
		    warn "IPv6 support re-enabled in __PACKAGE__, got disabled in file $caller_force_inet4[1] line $caller_force_inet4[2]";
		} else {
		    die "INET6 is not supported, install IO::Socket::IP";
		}
	    }
	} elsif ( /^:?debug(\d+)/ ) {
	    $DEBUG=$1;
	} else {
	    push @export,$_
	}
    }

    @_ = ( $class,@export );
    goto &Exporter::import;
}

my %SSL_OBJECT;
my %CREATED_IN_THIS_THREAD;
sub CLONE { %CREATED_IN_THIS_THREAD = (); }

# all keys specific for the current state of the socket
# these should be removed on close
my %all_my_conn_keys = map { $_ => 1 } qw(
    _SSL_fileno
    _SSL_object
    _SSL_opened
    _SSL_opening
    _SSL_read_closed
    _SSL_write_closed
    _SSL_rawfd
    _SSL_bio_socket
    _SSL_bio_sub
);

my %all_my_conn_and_cert_keys = (
    %all_my_conn_keys,
    _SSL_certificate => 1,
);

# all keys used internally, these should be cleaned up at end
# but not already on close
my %all_my_keys = (
    %all_my_conn_and_cert_keys,
    map { $_ => 1 } qw(
	_SSL_arguments
	_SSL_ctx
	_SSL_ioclass_upgraded
	_SSL_last_err
	_SSL_ocsp_verify
	_SSL_servername
	_SSL_msg_callback
    )



( run in 2.424 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )