�ɲɾ�����ӯ�����һ��ˣ��������С���˴��ͣ�������P���ҹ��ñ˽��ά�Բ��������˸߸ԣ�������ơ��ҹ��ñ�����ά�Բ���ˡ���˳^�ӣ������ӡ� ���ͯj�ӣ��ƺ���ӣ� ? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!PKp0]q protoent.pmnu[package Net::protoent; use strict; use 5.006_001; our $VERSION = '1.00'; our(@EXPORT, @EXPORT_OK, %EXPORT_TAGS); BEGIN { use Exporter (); @EXPORT = qw(getprotobyname getprotobynumber getprotoent getproto); @EXPORT_OK = qw( $p_name @p_aliases $p_proto ); %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] ); } use vars @EXPORT_OK; # Class::Struct forbids use of @ISA sub import { goto &Exporter::import } use Class::Struct qw(struct); struct 'Net::protoent' => [ name => '$', aliases => '@', proto => '$', ]; sub populate (@) { return unless @_; my $pob = new(); $p_name = $pob->[0] = $_[0]; @p_aliases = @{ $pob->[1] } = split ' ', $_[1]; $p_proto = $pob->[2] = $_[2]; return $pob; } sub getprotoent ( ) { populate(CORE::getprotoent()) } sub getprotobyname ($) { populate(CORE::getprotobyname(shift)) } sub getprotobynumber ($) { populate(CORE::getprotobynumber(shift)) } sub getproto ($;$) { no strict 'refs'; return &{'getprotoby' . ($_[0]=~/^\d+$/ ? 'number' : 'name')}(@_); } 1; __END__ =head1 NAME Net::protoent - by-name interface to Perl's built-in getproto*() functions =head1 SYNOPSIS use Net::protoent; $p = getprotobyname(shift || 'tcp') || die "no proto"; printf "proto for %s is %d, aliases are %s\n", $p->name, $p->proto, "@{$p->aliases}"; use Net::protoent qw(:FIELDS); getprotobyname(shift || 'tcp') || die "no proto"; print "proto for $p_name is $p_proto, aliases are @p_aliases\n"; =head1 DESCRIPTION This module's default exports override the core getprotoent(), getprotobyname(), and getnetbyport() functions, replacing them with versions that return "Net::protoent" objects. They take default second arguments of "tcp". This object has methods that return the similarly named structure field name from the C's protoent structure from F; namely name, aliases, and proto. The aliases method returns an array reference, the rest scalars. You may also import all the structure fields directly into your namespace as regular variables using the :FIELDS import tag. (Note that this still overrides your core functions.) Access these fields as variables named with a preceding C. Thus, C<$proto_obj-Ename()> corresponds to $p_name if you import the fields. Array references are available as regular array variables, so for example C<@{ $proto_obj-Ealiases() }> would be simply @p_aliases. The getproto() function is a simple front-end that forwards a numeric argument to getprotobyport(), and the rest to getprotobyname(). To access this functionality without the core overrides, pass the C an empty import list, and then access function functions with their full qualified names. On the other hand, the built-ins are still available via the C pseudo-package. =head1 NOTE While this class is currently implemented using the Class::Struct module to build a struct-like class, you shouldn't rely upon this. =head1 AUTHOR Tom Christiansen PKp0] hostent.pmnu[package Net::hostent; use strict; use 5.006_001; our $VERSION = '1.01'; our(@EXPORT, @EXPORT_OK, %EXPORT_TAGS); BEGIN { use Exporter (); @EXPORT = qw(gethostbyname gethostbyaddr gethost); @EXPORT_OK = qw( $h_name @h_aliases $h_addrtype $h_length @h_addr_list $h_addr ); %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] ); } use vars @EXPORT_OK; # Class::Struct forbids use of @ISA sub import { goto &Exporter::import } use Class::Struct qw(struct); struct 'Net::hostent' => [ name => '$', aliases => '@', addrtype => '$', 'length' => '$', addr_list => '@', ]; sub addr { shift->addr_list->[0] } sub populate (@) { return unless @_; my $hob = new(); $h_name = $hob->[0] = $_[0]; @h_aliases = @{ $hob->[1] } = split ' ', $_[1]; $h_addrtype = $hob->[2] = $_[2]; $h_length = $hob->[3] = $_[3]; $h_addr = $_[4]; @h_addr_list = @{ $hob->[4] } = @_[ (4 .. $#_) ]; return $hob; } sub gethostbyname ($) { populate(CORE::gethostbyname(shift)) } sub gethostbyaddr ($;$) { my ($addr, $addrtype); $addr = shift; require Socket unless @_; $addrtype = @_ ? shift : Socket::AF_INET(); populate(CORE::gethostbyaddr($addr, $addrtype)) } sub gethost($) { if ($_[0] =~ /^\d+(?:\.\d+(?:\.\d+(?:\.\d+)?)?)?$/) { require Socket; &gethostbyaddr(Socket::inet_aton(shift)); } else { &gethostbyname; } } 1; __END__ =head1 NAME Net::hostent - by-name interface to Perl's built-in gethost*() functions =head1 SYNOPSIS use Net::hostent; =head1 DESCRIPTION This module's default exports override the core gethostbyname() and gethostbyaddr() functions, replacing them with versions that return "Net::hostent" objects. This object has methods that return the similarly named structure field name from the C's hostent structure from F; namely name, aliases, addrtype, length, and addr_list. The aliases and addr_list methods return array reference, the rest scalars. The addr method is equivalent to the zeroth element in the addr_list array reference. You may also import all the structure fields directly into your namespace as regular variables using the :FIELDS import tag. (Note that this still overrides your core functions.) Access these fields as variables named with a preceding C. Thus, C<$host_obj-Ename()> corresponds to $h_name if you import the fields. Array references are available as regular array variables, so for example C<@{ $host_obj-Ealiases() }> would be simply @h_aliases. The gethost() function is a simple front-end that forwards a numeric argument to gethostbyaddr() by way of Socket::inet_aton, and the rest to gethostbyname(). To access this functionality without the core overrides, pass the C an empty import list, and then access function functions with their full qualified names. On the other hand, the built-ins are still available via the C pseudo-package. =head1 EXAMPLES use Net::hostent; use Socket; @ARGV = ('netscape.com') unless @ARGV; for $host ( @ARGV ) { unless ($h = gethost($host)) { warn "$0: no such host: $host\n"; next; } printf "\n%s is %s%s\n", $host, lc($h->name) eq lc($host) ? "" : "*really* ", $h->name; print "\taliases are ", join(", ", @{$h->aliases}), "\n" if @{$h->aliases}; if ( @{$h->addr_list} > 1 ) { my $i; for $addr ( @{$h->addr_list} ) { printf "\taddr #%d is [%s]\n", $i++, inet_ntoa($addr); } } else { printf "\taddress is [%s]\n", inet_ntoa($h->addr); } if ($h = gethostbyaddr($h->addr)) { if (lc($h->name) ne lc($host)) { printf "\tThat addr reverses to host %s!\n", $h->name; $host = $h->name; redo; } } } =head1 NOTE While this class is currently implemented using the Class::Struct module to build a struct-like class, you shouldn't rely upon this. =head1 AUTHOR Tom Christiansen PKp0]6 B servent.pmnu[package Net::servent; use strict; use 5.006_001; our $VERSION = '1.01'; our(@EXPORT, @EXPORT_OK, %EXPORT_TAGS); BEGIN { use Exporter (); @EXPORT = qw(getservbyname getservbyport getservent getserv); @EXPORT_OK = qw( $s_name @s_aliases $s_port $s_proto ); %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] ); } use vars @EXPORT_OK; # Class::Struct forbids use of @ISA sub import { goto &Exporter::import } use Class::Struct qw(struct); struct 'Net::servent' => [ name => '$', aliases => '@', port => '$', proto => '$', ]; sub populate (@) { return unless @_; my $sob = new(); $s_name = $sob->[0] = $_[0]; @s_aliases = @{ $sob->[1] } = split ' ', $_[1]; $s_port = $sob->[2] = $_[2]; $s_proto = $sob->[3] = $_[3]; return $sob; } sub getservent ( ) { populate(CORE::getservent()) } sub getservbyname ($;$) { populate(CORE::getservbyname(shift,shift||'tcp')) } sub getservbyport ($;$) { populate(CORE::getservbyport(shift,shift||'tcp')) } sub getserv ($;$) { no strict 'refs'; return &{'getservby' . ($_[0]=~/^\d+$/ ? 'port' : 'name')}(@_); } 1; __END__ =head1 NAME Net::servent - by-name interface to Perl's built-in getserv*() functions =head1 SYNOPSIS use Net::servent; $s = getservbyname(shift || 'ftp') || die "no service"; printf "port for %s is %s, aliases are %s\n", $s->name, $s->port, "@{$s->aliases}"; use Net::servent qw(:FIELDS); getservbyname(shift || 'ftp') || die "no service"; print "port for $s_name is $s_port, aliases are @s_aliases\n"; =head1 DESCRIPTION This module's default exports override the core getservent(), getservbyname(), and getnetbyport() functions, replacing them with versions that return "Net::servent" objects. They take default second arguments of "tcp". This object has methods that return the similarly named structure field name from the C's servent structure from F; namely name, aliases, port, and proto. The aliases method returns an array reference, the rest scalars. You may also import all the structure fields directly into your namespace as regular variables using the :FIELDS import tag. (Note that this still overrides your core functions.) Access these fields as variables named with a preceding C. Thus, C<$serv_obj-Ename()> corresponds to $s_name if you import the fields. Array references are available as regular array variables, so for example C<@{ $serv_obj-Ealiases()}> would be simply @s_aliases. The getserv() function is a simple front-end that forwards a numeric argument to getservbyport(), and the rest to getservbyname(). To access this functionality without the core overrides, pass the C an empty import list, and then access function functions with their full qualified names. On the other hand, the built-ins are still available via the C pseudo-package. =head1 EXAMPLES use Net::servent qw(:FIELDS); while (@ARGV) { my ($service, $proto) = ((split m!/!, shift), 'tcp'); my $valet = getserv($service, $proto); unless ($valet) { warn "$0: No service: $service/$proto\n" next; } printf "service $service/$proto is port %d\n", $valet->port; print "alias are @s_aliases\n" if @s_aliases; } =head1 NOTE While this class is currently implemented using the Class::Struct module to build a struct-like class, you shouldn't rely upon this. =head1 AUTHOR Tom Christiansen PKp0]]8]8Ping.pmnu[package Net::Ping; require 5.002; require Exporter; use strict; use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION $def_timeout $def_proto $def_factor $def_family $max_datasize $pingstring $hires $source_verify $syn_forking); use Fcntl qw( F_GETFL F_SETFL O_NONBLOCK ); use Socket qw( SOCK_DGRAM SOCK_STREAM SOCK_RAW AF_INET PF_INET IPPROTO_TCP SOL_SOCKET SO_ERROR SO_BROADCAST IPPROTO_IP IP_TOS IP_TTL inet_ntoa inet_aton getnameinfo NI_NUMERICHOST sockaddr_in ); use POSIX qw( ENOTCONN ECONNREFUSED ECONNRESET EINPROGRESS EWOULDBLOCK EAGAIN WNOHANG ); use FileHandle; use Carp; use Time::HiRes; @ISA = qw(Exporter); @EXPORT = qw(pingecho); @EXPORT_OK = qw(wakeonlan); $VERSION = "2.55"; # Globals $def_timeout = 5; # Default timeout to wait for a reply $def_proto = "tcp"; # Default protocol to use for pinging $def_factor = 1.2; # Default exponential backoff rate. $def_family = AF_INET; # Default family. $max_datasize = 1024; # Maximum data bytes in a packet # The data we exchange with the server for the stream protocol $pingstring = "pingschwingping!\n"; $source_verify = 1; # Default is to verify source endpoint $syn_forking = 0; # Constants my $AF_INET6 = eval { Socket::AF_INET6() }; my $AF_UNSPEC = eval { Socket::AF_UNSPEC() }; my $AI_NUMERICHOST = eval { Socket::AI_NUMERICHOST() }; my $NI_NUMERICHOST = eval { Socket::NI_NUMERICHOST() }; my $IPPROTO_IPV6 = eval { Socket::IPPROTO_IPV6() }; #my $IPV6_HOPLIMIT = eval { Socket::IPV6_HOPLIMIT() }; # ping6 -h 0-255 my $qr_family = qr/^(?:(?:(:?ip)?v?(?:4|6))|${\AF_INET}|$AF_INET6)$/; my $qr_family4 = qr/^(?:(?:(:?ip)?v?4)|${\AF_INET})$/; if ($^O =~ /Win32/i) { # Hack to avoid this Win32 spewage: # Your vendor has not defined POSIX macro ECONNREFUSED my @pairs = (ECONNREFUSED => 10061, # "Unknown Error" Special Win32 Response? ENOTCONN => 10057, ECONNRESET => 10054, EINPROGRESS => 10036, EWOULDBLOCK => 10035, ); while (my $name = shift @pairs) { my $value = shift @pairs; # When defined, these all are non-zero unless (eval $name) { no strict 'refs'; *{$name} = defined prototype \&{$name} ? sub () {$value} : sub {$value}; } } # $syn_forking = 1; # XXX possibly useful in < Win2K ? }; # Description: The pingecho() subroutine is provided for backward # compatibility with the original Net::Ping. It accepts a host # name/IP and an optional timeout in seconds. Create a tcp ping # object and try pinging the host. The result of the ping is returned. sub pingecho { my ($host, # Name or IP number of host to ping $timeout # Optional timeout in seconds ) = @_; my ($p); # A ping object $p = Net::Ping->new("tcp", $timeout); $p->ping($host); # Going out of scope closes the connection } # Description: The new() method creates a new ping object. Optional # parameters may be specified for the protocol to use, the timeout in # seconds and the size in bytes of additional data which should be # included in the packet. # After the optional parameters are checked, the data is constructed # and a socket is opened if appropriate. The object is returned. sub new { my ($this, $proto, # Optional protocol to use for pinging $timeout, # Optional timeout in seconds $data_size, # Optional additional bytes of data $device, # Optional device to use $tos, # Optional ToS to set $ttl, # Optional TTL to set $family, # Optional address family (AF_INET) ) = @_; my $class = ref($this) || $this; my $self = {}; my ($cnt, # Count through data bytes $min_datasize # Minimum data bytes required ); bless($self, $class); if (ref $proto eq 'HASH') { # support named args for my $k (qw(proto timeout data_size device tos ttl family gateway host port bind retrans pingstring source_verify econnrefused dontfrag IPV6_USE_MIN_MTU IPV6_RECVPATHMTU IPV6_HOPLIMIT)) { if (exists $proto->{$k}) { $self->{$k} = $proto->{$k}; # some are still globals if ($k eq 'pingstring') { $pingstring = $proto->{$k} } if ($k eq 'source_verify') { $source_verify = $proto->{$k} } delete $proto->{$k}; } } if (%$proto) { croak("Invalid named argument: ",join(" ",keys (%$proto))); } $proto = $self->{'proto'}; } $proto = $def_proto unless $proto; # Determine the protocol croak('Protocol for ping must be "icmp", "icmpv6", "udp", "tcp", "syn", "stream" or "external"') unless $proto =~ m/^(icmp|icmpv6|udp|tcp|syn|stream|external)$/; $self->{proto} = $proto; $timeout = $def_timeout unless $timeout; # Determine the timeout croak("Default timeout for ping must be greater than 0 seconds") if $timeout <= 0; $self->{timeout} = $timeout; $self->{device} = $device; $self->{tos} = $tos; if ($self->{'host'}) { my $host = $self->{'host'}; my $ip = _resolv($host) or carp("could not resolve host $host"); $self->{host} = $ip; $self->{family} = $ip->{family}; } if ($self->{bind}) { my $addr = $self->{bind}; my $ip = _resolv($addr) or carp("could not resolve local addr $addr"); $self->{local_addr} = $ip; } else { $self->{local_addr} = undef; # Don't bind by default } if ($self->{proto} eq 'icmp') { croak('TTL must be from 0 to 255') if ($ttl && ($ttl < 0 || $ttl > 255)); $self->{ttl} = $ttl; } if ($family) { if ($family =~ $qr_family) { if ($family =~ $qr_family4) { $self->{family} = AF_INET; } else { $self->{family} = $AF_INET6; } } else { croak('Family must be "ipv4" or "ipv6"') } } else { $self->{family} = $def_family; } $min_datasize = ($proto eq "udp") ? 1 : 0; # Determine data size $data_size = $min_datasize unless defined($data_size) && $proto ne "tcp"; croak("Data for ping must be from $min_datasize to $max_datasize bytes") if ($data_size < $min_datasize) || ($data_size > $max_datasize); $data_size-- if $self->{proto} eq "udp"; # We provide the first byte $self->{data_size} = $data_size; $self->{data} = ""; # Construct data bytes for ($cnt = 0; $cnt < $self->{data_size}; $cnt++) { $self->{data} .= chr($cnt % 256); } # Default exponential backoff rate $self->{retrans} = $def_factor unless exists $self->{retrans}; # Default Connection refused behavior $self->{econnrefused} = undef unless exists $self->{econnrefused}; $self->{seq} = 0; # For counting packets if ($self->{proto} eq "udp") # Open a socket { $self->{proto_num} = eval { (getprotobyname('udp'))[2] } || croak("Can't udp protocol by name"); $self->{port_num} = $self->{port} || (getservbyname('echo', 'udp'))[2] || croak("Can't get udp echo port by name"); $self->{fh} = FileHandle->new(); socket($self->{fh}, PF_INET, SOCK_DGRAM, $self->{proto_num}) || croak("udp socket error - $!"); $self->_setopts(); } elsif ($self->{proto} eq "icmp") { croak("icmp ping requires root privilege") if !_isroot(); $self->{proto_num} = eval { (getprotobyname('icmp'))[2] } || croak("Can't get icmp protocol by name"); $self->{pid} = $$ & 0xffff; # Save lower 16 bits of pid $self->{fh} = FileHandle->new(); socket($self->{fh}, PF_INET, SOCK_RAW, $self->{proto_num}) || croak("icmp socket error - $!"); $self->_setopts(); if ($self->{'ttl'}) { setsockopt($self->{fh}, IPPROTO_IP, IP_TTL, pack("I*", $self->{'ttl'})) or croak "error configuring ttl to $self->{'ttl'} $!"; } } elsif ($self->{proto} eq "icmpv6") { croak("icmpv6 ping requires root privilege") if !_isroot(); croak("Wrong family $self->{family} for icmpv6 protocol") if $self->{family} and $self->{family} != $AF_INET6; $self->{family} = $AF_INET6; $self->{proto_num} = eval { (getprotobyname('ipv6-icmp'))[2] } || croak("Can't get ipv6-icmp protocol by name"); # 58 $self->{pid} = $$ & 0xffff; # Save lower 16 bits of pid $self->{fh} = FileHandle->new(); socket($self->{fh}, $AF_INET6, SOCK_RAW, $self->{proto_num}) || croak("icmp socket error - $!"); $self->_setopts(); if ($self->{'gateway'}) { my $g = $self->{gateway}; my $ip = _resolv($g) or croak("nonexistent gateway $g"); $self->{family} eq $AF_INET6 or croak("gateway requires the AF_INET6 family"); $ip->{family} eq $AF_INET6 or croak("gateway address needs to be IPv6"); my $IPV6_NEXTHOP = eval { Socket::IPV6_NEXTHOP() } || 48; # IPV6_3542NEXTHOP, or 21 setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_NEXTHOP, _pack_sockaddr_in($ip)) or croak "error configuring gateway to $g NEXTHOP $!"; } if (exists $self->{IPV6_USE_MIN_MTU}) { my $IPV6_USE_MIN_MTU = eval { Socket::IPV6_USE_MIN_MTU() } || 42; setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_USE_MIN_MTU, pack("I*", $self->{'IPV6_USE_MIN_MT'})) or croak "error configuring IPV6_USE_MIN_MT} $!"; } if (exists $self->{IPV6_RECVPATHMTU}) { my $IPV6_RECVPATHMTU = eval { Socket::IPV6_RECVPATHMTU() } || 43; setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_RECVPATHMTU, pack("I*", $self->{'RECVPATHMTU'})) or croak "error configuring IPV6_RECVPATHMTU $!"; } if ($self->{'tos'}) { my $proto = $self->{family} == AF_INET ? IPPROTO_IP : $IPPROTO_IPV6; setsockopt($self->{fh}, $proto, IP_TOS, pack("I*", $self->{'tos'})) or croak "error configuring tos to $self->{'tos'} $!"; } if ($self->{'ttl'}) { my $proto = $self->{family} == AF_INET ? IPPROTO_IP : $IPPROTO_IPV6; setsockopt($self->{fh}, $proto, IP_TTL, pack("I*", $self->{'ttl'})) or croak "error configuring ttl to $self->{'ttl'} $!"; } } elsif ($self->{proto} eq "tcp" || $self->{proto} eq "stream") { $self->{proto_num} = eval { (getprotobyname('tcp'))[2] } || croak("Can't get tcp protocol by name"); $self->{port_num} = $self->{port} || (getservbyname('echo', 'tcp'))[2] || croak("Can't get tcp echo port by name"); $self->{fh} = FileHandle->new(); } elsif ($self->{proto} eq "syn") { $self->{proto_num} = eval { (getprotobyname('tcp'))[2] } || croak("Can't get tcp protocol by name"); $self->{port_num} = (getservbyname('echo', 'tcp'))[2] || croak("Can't get tcp echo port by name"); if ($syn_forking) { $self->{fork_rd} = FileHandle->new(); $self->{fork_wr} = FileHandle->new(); pipe($self->{fork_rd}, $self->{fork_wr}); $self->{fh} = FileHandle->new(); $self->{good} = {}; $self->{bad} = {}; } else { $self->{wbits} = ""; $self->{bad} = {}; } $self->{syn} = {}; $self->{stop_time} = 0; } return($self); } # Description: Set the local IP address from which pings will be sent. # For ICMP, UDP and TCP pings, just saves the address to be used when # the socket is opened. Returns non-zero if successful; croaks on error. sub bind { my ($self, $local_addr # Name or IP number of local interface ) = @_; my ($ip, # Hash of addr (string), addr_in (packed), family $h # resolved hash ); croak("Usage: \$p->bind(\$local_addr)") unless @_ == 2; croak("already bound") if defined($self->{local_addr}) && ($self->{proto} eq "udp" || $self->{proto} eq "icmp"); $ip = $self->_resolv($local_addr); carp("nonexistent local address $local_addr") unless defined($ip); $self->{local_addr} = $ip; if (($self->{proto} ne "udp") && ($self->{proto} ne "icmp") && ($self->{proto} ne "tcp") && ($self->{proto} ne "syn")) { croak("Unknown protocol \"$self->{proto}\" in bind()"); } return 1; } # Description: A select() wrapper that compensates for platform # peculiarities. sub mselect { if ($_[3] > 0 and $^O eq 'MSWin32') { # On windows, select() doesn't process the message loop, # but sleep() will, allowing alarm() to interrupt the latter. # So we chop up the timeout into smaller pieces and interleave # select() and sleep() calls. my $t = $_[3]; my $gran = 0.5; # polling granularity in seconds my @args = @_; while (1) { $gran = $t if $gran > $t; my $nfound = select($_[0], $_[1], $_[2], $gran); undef $nfound if $nfound == -1; $t -= $gran; return $nfound if $nfound or !defined($nfound) or $t <= 0; sleep(0); ($_[0], $_[1], $_[2]) = @args; } } else { my $nfound = select($_[0], $_[1], $_[2], $_[3]); undef $nfound if $nfound == -1; return $nfound; } } # Description: Allow UDP source endpoint comparison to be # skipped for those remote interfaces that do # not response from the same endpoint. sub source_verify { my $self = shift; $source_verify = 1 unless defined ($source_verify = ((defined $self) && (ref $self)) ? shift() : $self); } # Description: Set whether or not the connect # behavior should enforce remote service # availability as well as reachability. sub service_check { my $self = shift; $self->{econnrefused} = 1 unless defined ($self->{econnrefused} = shift()); } sub tcp_service_check { service_check(@_); } # Description: Set exponential backoff for retransmission. # Should be > 1 to retain exponential properties. # If set to 0, retransmissions are disabled. sub retrans { my $self = shift; $self->{retrans} = shift; } sub _IsAdminUser { return unless $^O eq 'MSWin32' or $^O eq "cygwin"; return unless eval { require Win32 }; return unless defined &Win32::IsAdminUser; return Win32::IsAdminUser(); } sub _isroot { if (($> and $^O ne 'VMS' and $^O ne 'cygwin') or (($^O eq 'MSWin32' or $^O eq 'cygwin') and !_IsAdminUser()) or ($^O eq 'VMS' and (`write sys\$output f\$privilege("SYSPRV")` =~ m/FALSE/))) { return 0; } else { return 1; } } # Description: Sets ipv6 reachability # REACHCONF was removed in RFC3542, ping6 -R supports it. requires root. sub IPV6_REACHCONF { my $self = shift; my $on = shift; if ($on) { my $reachconf = eval { Socket::IPV6_REACHCONF() }; if (!$reachconf) { carp "IPV6_REACHCONF not supported on this platform"; return 0; } if (!_isroot()) { carp "IPV6_REACHCONF requires root permissions"; return 0; } $self->{IPV6_REACHCONF} = 1; } else { return $self->{IPV6_REACHCONF}; } } # Description: set it on or off. sub IPV6_USE_MIN_MTU { my $self = shift; my $on = shift; if (defined $on) { my $IPV6_USE_MIN_MTU = eval { Socket::IPV6_USE_MIN_MTU() } || 43; #if (!$IPV6_USE_MIN_MTU) { # carp "IPV6_USE_MIN_MTU not supported on this platform"; # return 0; #} $self->{IPV6_USE_MIN_MTU} = $on ? 1 : 0; setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_USE_MIN_MTU, pack("I*", $self->{'IPV6_USE_MIN_MT'})) or croak "error configuring IPV6_USE_MIN_MT} $!"; } else { return $self->{IPV6_USE_MIN_MTU}; } } # Description: notify an according MTU sub IPV6_RECVPATHMTU { my $self = shift; my $on = shift; if ($on) { my $IPV6_RECVPATHMTU = eval { Socket::IPV6_RECVPATHMTU() } || 43; #if (!$RECVPATHMTU) { # carp "IPV6_RECVPATHMTU not supported on this platform"; # return 0; #} $self->{IPV6_RECVPATHMTU} = 1; setsockopt($self->{fh}, $IPPROTO_IPV6, $IPV6_RECVPATHMTU, pack("I*", $self->{'IPV6_RECVPATHMTU'})) or croak "error configuring IPV6_RECVPATHMTU} $!"; } else { return $self->{IPV6_RECVPATHMTU}; } } # Description: allows the module to use milliseconds as returned by # the Time::HiRes module $hires = 1; sub hires { my $self = shift; $hires = 1 unless defined ($hires = ((defined $self) && (ref $self)) ? shift() : $self); } sub time { return $hires ? Time::HiRes::time() : CORE::time(); } # Description: Sets or clears the O_NONBLOCK flag on a file handle. sub socket_blocking_mode { my ($self, $fh, # the file handle whose flags are to be modified $block) = @_; # if true then set the blocking # mode (clear O_NONBLOCK), otherwise # set the non-blocking mode (set O_NONBLOCK) my $flags; if ($^O eq 'MSWin32' || $^O eq 'VMS') { # FIONBIO enables non-blocking sockets on windows and vms. # FIONBIO is (0x80000000|(4<<16)|(ord('f')<<8)|126), as per winsock.h, ioctl.h my $f = 0x8004667e; my $v = pack("L", $block ? 0 : 1); ioctl($fh, $f, $v) or croak("ioctl failed: $!"); return; } if ($flags = fcntl($fh, F_GETFL, 0)) { $flags = $block ? ($flags & ~O_NONBLOCK) : ($flags | O_NONBLOCK); if (!fcntl($fh, F_SETFL, $flags)) { croak("fcntl F_SETFL: $!"); } } else { croak("fcntl F_GETFL: $!"); } } # Description: Ping a host name or IP number with an optional timeout. # First lookup the host, and return undef if it is not found. Otherwise # perform the specific ping method based on the protocol. Return the # result of the ping. sub ping { my ($self, $host, # Name or IP number of host to ping $timeout, # Seconds after which ping times out $family, # Address family ) = @_; my ($ip, # Hash of addr (string), addr_in (packed), family $ret, # The return value $ping_time, # When ping began ); $host = $self->{host} if !defined $host and $self->{host}; croak("Usage: \$p->ping([ \$host [, \$timeout [, \$family]]])") if @_ > 4 or !$host; $timeout = $self->{timeout} unless $timeout; croak("Timeout must be greater than 0 seconds") if $timeout <= 0; if ($family) { if ($family =~ $qr_family) { if ($family =~ $qr_family4) { $self->{family_local} = AF_INET; } else { $self->{family_local} = $AF_INET6; } } else { croak('Family must be "ipv4" or "ipv6"') } } else { $self->{family_local} = $self->{family}; } $ip = $self->_resolv($host); return () unless defined($ip); # Does host exist? # Dispatch to the appropriate routine. $ping_time = &time(); if ($self->{proto} eq "external") { $ret = $self->ping_external($ip, $timeout); } elsif ($self->{proto} eq "udp") { $ret = $self->ping_udp($ip, $timeout); } elsif ($self->{proto} eq "icmp") { $ret = $self->ping_icmp($ip, $timeout); } elsif ($self->{proto} eq "icmpv6") { $ret = $self->ping_icmpv6($ip, $timeout); } elsif ($self->{proto} eq "tcp") { $ret = $self->ping_tcp($ip, $timeout); } elsif ($self->{proto} eq "stream") { $ret = $self->ping_stream($ip, $timeout); } elsif ($self->{proto} eq "syn") { $ret = $self->ping_syn($host, $ip, $ping_time, $ping_time+$timeout); } else { croak("Unknown protocol \"$self->{proto}\" in ping()"); } return wantarray ? ($ret, &time() - $ping_time, $self->ntop($ip)) : $ret; } # Uses Net::Ping::External to do an external ping. sub ping_external { my ($self, $ip, # Hash of addr (string), addr_in (packed), family $timeout, # Seconds after which ping times out $family ) = @_; $ip = $self->{host} if !defined $ip and $self->{host}; $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; my @addr = exists $ip->{addr_in} ? ('ip' => $ip->{addr_in}) : ('host' => $ip->{host}); eval { require Net::Ping::External; } or croak('Protocol "external" not supported on your system: Net::Ping::External not found'); return Net::Ping::External::ping(@addr, timeout => $timeout, family => $family); } # h2ph "asm/socket.h" # require "asm/socket.ph"; use constant SO_BINDTODEVICE => 25; use constant ICMP_ECHOREPLY => 0; # ICMP packet types use constant ICMPv6_ECHOREPLY => 129; # ICMP packet types use constant ICMP_UNREACHABLE => 3; # ICMP packet types use constant ICMPv6_UNREACHABLE => 1; # ICMP packet types use constant ICMP_ECHO => 8; use constant ICMPv6_ECHO => 128; use constant ICMP_TIME_EXCEEDED => 11; # ICMP packet types use constant ICMP_PARAMETER_PROBLEM => 12; # ICMP packet types use constant ICMP_STRUCT => "C2 n3 A"; # Structure of a minimal ICMP packet use constant SUBCODE => 0; # No ICMP subcode for ECHO and ECHOREPLY use constant ICMP_FLAGS => 0; # No special flags for send or recv use constant ICMP_PORT => 0; # No port with ICMP use constant IP_MTU_DISCOVER => 10; # linux only sub ping_icmp { my ($self, $ip, # Hash of addr (string), addr_in (packed), family $timeout # Seconds after which ping times out ) = @_; my ($saddr, # sockaddr_in with port and ip $checksum, # Checksum of ICMP packet $msg, # ICMP packet to send $len_msg, # Length of $msg $rbits, # Read bits, filehandles for reading $nfound, # Number of ready filehandles found $finish_time, # Time ping should be finished $done, # set to 1 when we are done $ret, # Return value $recv_msg, # Received message including IP header $from_saddr, # sockaddr_in of sender $from_port, # Port packet was sent from $from_ip, # Packed IP of sender $from_type, # ICMP type $from_subcode, # ICMP subcode $from_chk, # ICMP packet checksum $from_pid, # ICMP packet id $from_seq, # ICMP packet sequence $from_msg # ICMP message ); $ip = $self->{host} if !defined $ip and $self->{host}; $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; socket($self->{fh}, $ip->{family}, SOCK_RAW, $self->{proto_num}) || croak("icmp socket error - $!"); if (defined $self->{local_addr} && !CORE::bind($self->{fh}, _pack_sockaddr_in(0, $self->{local_addr}))) { croak("icmp bind error - $!"); } $self->_setopts(); $self->{seq} = ($self->{seq} + 1) % 65536; # Increment sequence $checksum = 0; # No checksum for starters if ($ip->{family} == AF_INET) { $msg = pack(ICMP_STRUCT . $self->{data_size}, ICMP_ECHO, SUBCODE, $checksum, $self->{pid}, $self->{seq}, $self->{data}); } else { # how to get SRC my $pseudo_header = pack('a16a16Nnn', $ip->{addr_in}, $ip->{addr_in}, 8+length($self->{data}), "\0", 0x003a); $msg = pack(ICMP_STRUCT . $self->{data_size}, ICMPv6_ECHO, SUBCODE, $checksum, $self->{pid}, $self->{seq}, $self->{data}); $msg = $pseudo_header.$msg } $checksum = Net::Ping->checksum($msg); if ($ip->{family} == AF_INET) { $msg = pack(ICMP_STRUCT . $self->{data_size}, ICMP_ECHO, SUBCODE, $checksum, $self->{pid}, $self->{seq}, $self->{data}); } else { $msg = pack(ICMP_STRUCT . $self->{data_size}, ICMPv6_ECHO, SUBCODE, $checksum, $self->{pid}, $self->{seq}, $self->{data}); } $len_msg = length($msg); $saddr = _pack_sockaddr_in(ICMP_PORT, $ip); $self->{from_ip} = undef; $self->{from_type} = undef; $self->{from_subcode} = undef; send($self->{fh}, $msg, ICMP_FLAGS, $saddr); # Send the message $rbits = ""; vec($rbits, $self->{fh}->fileno(), 1) = 1; $ret = 0; $done = 0; $finish_time = &time() + $timeout; # Must be done by this time while (!$done && $timeout > 0) # Keep trying if we have time { $nfound = mselect((my $rout=$rbits), undef, undef, $timeout); # Wait for packet $timeout = $finish_time - &time(); # Get remaining time if (!defined($nfound)) # Hmm, a strange error { $ret = undef; $done = 1; } elsif ($nfound) # Got a packet from somewhere { $recv_msg = ""; $from_pid = -1; $from_seq = -1; $from_saddr = recv($self->{fh}, $recv_msg, 1500, ICMP_FLAGS); ($from_port, $from_ip) = _unpack_sockaddr_in($from_saddr, $ip->{family}); ($from_type, $from_subcode) = unpack("C2", substr($recv_msg, 20, 2)); if ($from_type == ICMP_ECHOREPLY) { ($from_pid, $from_seq) = unpack("n3", substr($recv_msg, 24, 4)) if length $recv_msg >= 28; } elsif ($from_type == ICMPv6_ECHOREPLY) { ($from_pid, $from_seq) = unpack("n3", substr($recv_msg, 24, 4)) if length $recv_msg >= 28; } else { ($from_pid, $from_seq) = unpack("n3", substr($recv_msg, 52, 4)) if length $recv_msg >= 56; } $self->{from_ip} = $from_ip; $self->{from_type} = $from_type; $self->{from_subcode} = $from_subcode; next if ($from_pid != $self->{pid}); next if ($from_seq != $self->{seq}); if (! $source_verify || ($self->ntop($from_ip) eq $self->ntop($ip))) { # Does the packet check out? if (($from_type == ICMP_ECHOREPLY) || ($from_type == ICMPv6_ECHOREPLY)) { $ret = 1; $done = 1; } elsif (($from_type == ICMP_UNREACHABLE) || ($from_type == ICMPv6_UNREACHABLE)) { $done = 1; } elsif ($from_type == ICMP_TIME_EXCEEDED) { $ret = 0; $done = 1; } } } else { # Oops, timed out $done = 1; } } return $ret; } sub ping_icmpv6 { shift->ping_icmp(@_); } sub icmp_result { my ($self) = @_; my $addr = $self->{from_ip} || ""; $addr = "\0\0\0\0" unless 4 == length $addr; return ($self->ntop($addr),($self->{from_type} || 0), ($self->{from_subcode} || 0)); } # Description: Do a checksum on the message. Basically sum all of # the short words and fold the high order bits into the low order bits. sub checksum { my ($class, $msg # The message to checksum ) = @_; my ($len_msg, # Length of the message $num_short, # The number of short words in the message $short, # One short word $chk # The checksum ); $len_msg = length($msg); $num_short = int($len_msg / 2); $chk = 0; foreach $short (unpack("n$num_short", $msg)) { $chk += $short; } # Add the odd byte in $chk += (unpack("C", substr($msg, $len_msg - 1, 1)) << 8) if $len_msg % 2; $chk = ($chk >> 16) + ($chk & 0xffff); # Fold high into low return(~(($chk >> 16) + $chk) & 0xffff); # Again and complement } # Description: Perform a tcp echo ping. Since a tcp connection is # host specific, we have to open and close each connection here. We # can't just leave a socket open. Because of the robust nature of # tcp, it will take a while before it gives up trying to establish a # connection. Therefore, we use select() on a non-blocking socket to # check against our timeout. No data bytes are actually # sent since the successful establishment of a connection is proof # enough of the reachability of the remote host. Also, tcp is # expensive and doesn't need our help to add to the overhead. sub ping_tcp { my ($self, $ip, # Hash of addr (string), addr_in (packed), family $timeout # Seconds after which ping times out ) = @_; my ($ret # The return value ); $ip = $self->{host} if !defined $ip and $self->{host}; $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; $! = 0; $ret = $self -> tcp_connect( $ip, $timeout); if (!$self->{econnrefused} && $! == ECONNREFUSED) { $ret = 1; # "Connection refused" means reachable } $self->{fh}->close(); return $ret; } sub tcp_connect { my ($self, $ip, # Hash of addr (string), addr_in (packed), family $timeout # Seconds after which connect times out ) = @_; my ($saddr); # Packed IP and Port $ip = $self->{host} if !defined $ip and $self->{host}; $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; $saddr = _pack_sockaddr_in($self->{port_num}, $ip); my $ret = 0; # Default to unreachable my $do_socket = sub { socket($self->{fh}, $ip->{family}, SOCK_STREAM, $self->{proto_num}) || croak("tcp socket error - $!"); if (defined $self->{local_addr} && !CORE::bind($self->{fh}, _pack_sockaddr_in(0, $self->{local_addr}))) { croak("tcp bind error - $!"); } $self->_setopts(); }; my $do_connect = sub { $self->{ip} = $ip->{addr_in}; # ECONNREFUSED is 10061 on MSWin32. If we pass it as child error through $?, # we'll get (10061 & 255) = 77, so we cannot check it in the parent process. return ($ret = connect($self->{fh}, $saddr) || ($! == ECONNREFUSED && !$self->{econnrefused})); }; my $do_connect_nb = sub { # Set O_NONBLOCK property on filehandle $self->socket_blocking_mode($self->{fh}, 0); # start the connection attempt if (!connect($self->{fh}, $saddr)) { if ($! == ECONNREFUSED) { $ret = 1 unless $self->{econnrefused}; } elsif ($! != EINPROGRESS && ($^O ne 'MSWin32' || $! != EWOULDBLOCK)) { # EINPROGRESS is the expected error code after a connect() # on a non-blocking socket. But if the kernel immediately # determined that this connect() will never work, # Simply respond with "unreachable" status. # (This can occur on some platforms with errno # EHOSTUNREACH or ENETUNREACH.) return 0; } else { # Got the expected EINPROGRESS. # Just wait for connection completion... my ($wbits, $wout, $wexc); $wout = $wexc = $wbits = ""; vec($wbits, $self->{fh}->fileno, 1) = 1; my $nfound = mselect(undef, ($wout = $wbits), ($^O eq 'MSWin32' ? ($wexc = $wbits) : undef), $timeout); warn("select: $!") unless defined $nfound; if ($nfound && vec($wout, $self->{fh}->fileno, 1)) { # the socket is ready for writing so the connection # attempt completed. test whether the connection # attempt was successful or not if (getpeername($self->{fh})) { # Connection established to remote host $ret = 1; } else { # TCP ACK will never come from this host # because there was an error connecting. # This should set $! to the correct error. my $char; sysread($self->{fh},$char,1); $! = ECONNREFUSED if ($! == EAGAIN && $^O =~ /cygwin/i); $ret = 1 if (!$self->{econnrefused} && $! == ECONNREFUSED); } } else { # the connection attempt timed out (or there were connect # errors on Windows) if ($^O =~ 'MSWin32') { # If the connect will fail on a non-blocking socket, # winsock reports ECONNREFUSED as an exception, and we # need to fetch the socket-level error code via getsockopt() # instead of using the thread-level error code that is in $!. if ($nfound && vec($wexc, $self->{fh}->fileno, 1)) { $! = unpack("i", getsockopt($self->{fh}, SOL_SOCKET, SO_ERROR)); } } } } } else { # Connection established to remote host $ret = 1; } # Unset O_NONBLOCK property on filehandle $self->socket_blocking_mode($self->{fh}, 1); $self->{ip} = $ip->{addr_in}; return $ret; }; if ($syn_forking) { # Buggy Winsock API doesn't allow nonblocking connect. # Hence, if our OS is Windows, we need to create a separate # process to do the blocking connect attempt. # XXX Above comments are not true at least for Win2K, where # nonblocking connect works. $| = 1; # Clear buffer prior to fork to prevent duplicate flushing. $self->{'tcp_chld'} = fork; if (!$self->{'tcp_chld'}) { if (!defined $self->{'tcp_chld'}) { # Fork did not work warn "Fork error: $!"; return 0; } &{ $do_socket }(); # Try a slow blocking connect() call # and report the status to the parent. if ( &{ $do_connect }() ) { $self->{fh}->close(); # No error exit 0; } else { # Pass the error status to the parent # Make sure that $! <= 255 exit($! <= 255 ? $! : 255); } } &{ $do_socket }(); my $patience = &time() + $timeout; my ($child, $child_errno); $? = 0; $child_errno = 0; # Wait up to the timeout # And clean off the zombie do { $child = waitpid($self->{'tcp_chld'}, &WNOHANG()); $child_errno = $? >> 8; select(undef, undef, undef, 0.1); } while &time() < $patience && $child != $self->{'tcp_chld'}; if ($child == $self->{'tcp_chld'}) { if ($self->{proto} eq "stream") { # We need the socket connected here, in parent # Should be safe to connect because the child finished # within the timeout &{ $do_connect }(); } # $ret cannot be set by the child process $ret = !$child_errno; } else { # Time must have run out. # Put that choking client out of its misery kill "KILL", $self->{'tcp_chld'}; # Clean off the zombie waitpid($self->{'tcp_chld'}, 0); $ret = 0; } delete $self->{'tcp_chld'}; $! = $child_errno; } else { # Otherwise don't waste the resources to fork &{ $do_socket }(); &{ $do_connect_nb }(); } return $ret; } sub DESTROY { my $self = shift; if ($self->{'proto'} eq 'tcp' && $self->{'tcp_chld'}) { # Put that choking client out of its misery kill "KILL", $self->{'tcp_chld'}; # Clean off the zombie waitpid($self->{'tcp_chld'}, 0); } } # This writes the given string to the socket and then reads it # back. It returns 1 on success, 0 on failure. sub tcp_echo { my ($self, $timeout, $pingstring) = @_; $timeout = $self->{timeout} if !defined $timeout and $self->{timeout}; $pingstring = $self->{pingstring} if !defined $pingstring and $self->{pingstring}; my $ret = undef; my $time = &time(); my $wrstr = $pingstring; my $rdstr = ""; eval <<'EOM'; do { my $rin = ""; vec($rin, $self->{fh}->fileno(), 1) = 1; my $rout = undef; if($wrstr) { $rout = ""; vec($rout, $self->{fh}->fileno(), 1) = 1; } if(mselect($rin, $rout, undef, ($time + $timeout) - &time())) { if($rout && vec($rout,$self->{fh}->fileno(),1)) { my $num = syswrite($self->{fh}, $wrstr, length $wrstr); if($num) { # If it was a partial write, update and try again. $wrstr = substr($wrstr,$num); } else { # There was an error. $ret = 0; } } if(vec($rin,$self->{fh}->fileno(),1)) { my $reply; if(sysread($self->{fh},$reply,length($pingstring)-length($rdstr))) { $rdstr .= $reply; $ret = 1 if $rdstr eq $pingstring; } else { # There was an error. $ret = 0; } } } } until &time() > ($time + $timeout) || defined($ret); EOM return $ret; } # Description: Perform a stream ping. If the tcp connection isn't # already open, it opens it. It then sends some data and waits for # a reply. It leaves the stream open on exit. sub ping_stream { my ($self, $ip, # Hash of addr (string), addr_in (packed), family $timeout # Seconds after which ping times out ) = @_; # Open the stream if it's not already open if(!defined $self->{fh}->fileno()) { $self->tcp_connect($ip, $timeout) or return 0; } croak "tried to switch servers while stream pinging" if $self->{ip} ne $ip->{addr_in}; return $self->tcp_echo($timeout, $pingstring); } # Description: opens the stream. You would do this if you want to # separate the overhead of opening the stream from the first ping. sub open { my ($self, $host, # Host or IP address $timeout, # Seconds after which open times out $family ) = @_; my $ip; # Hash of addr (string), addr_in (packed), family $host = $self->{host} unless defined $host; if ($family) { if ($family =~ $qr_family) { if ($family =~ $qr_family4) { $self->{family_local} = AF_INET; } else { $self->{family_local} = $AF_INET6; } } else { croak('Family must be "ipv4" or "ipv6"') } } else { $self->{family_local} = $self->{family}; } $timeout = $self->{timeout} unless $timeout; $ip = $self->_resolv($host); if ($self->{proto} eq "stream") { if (defined($self->{fh}->fileno())) { croak("socket is already open"); } else { return () unless $ip; $self->tcp_connect($ip, $timeout); } } } sub _dontfrag { my $self = shift; # bsd solaris my $IP_DONTFRAG = eval { Socket::IP_DONTFRAG() }; if ($IP_DONTFRAG) { my $i = 1; setsockopt($self->{fh}, IPPROTO_IP, $IP_DONTFRAG, pack("I*", $i)) or croak "error configuring IP_DONTFRAG $!"; # Linux needs more: Path MTU Discovery as defined in RFC 1191 # For non SOCK_STREAM sockets it is the user's responsibility to packetize # the data in MTU sized chunks and to do the retransmits if necessary. # The kernel will reject packets that are bigger than the known path # MTU if this flag is set (with EMSGSIZE). if ($^O eq 'linux') { my $i = 2; # IP_PMTUDISC_DO setsockopt($self->{fh}, IPPROTO_IP, IP_MTU_DISCOVER, pack("I*", $i)) or croak "error configuring IP_MTU_DISCOVER $!"; } } } # SO_BINDTODEVICE + IP_TOS sub _setopts { my $self = shift; if ($self->{'device'}) { setsockopt($self->{fh}, SOL_SOCKET, SO_BINDTODEVICE, pack("Z*", $self->{'device'})) or croak "error binding to device $self->{'device'} $!"; } if ($self->{'tos'}) { # need to re-apply ToS (RT #6706) setsockopt($self->{fh}, IPPROTO_IP, IP_TOS, pack("I*", $self->{'tos'})) or croak "error applying tos to $self->{'tos'} $!"; } if ($self->{'dontfrag'}) { $self->_dontfrag; } } # Description: Perform a udp echo ping. Construct a message of # at least the one-byte sequence number and any additional data bytes. # Send the message out and wait for a message to come back. If we # get a message, make sure all of its parts match. If they do, we are # done. Otherwise go back and wait for the message until we run out # of time. Return the result of our efforts. use constant UDP_FLAGS => 0; # Nothing special on send or recv sub ping_udp { my ($self, $ip, # Hash of addr (string), addr_in (packed), family $timeout # Seconds after which ping times out ) = @_; my ($saddr, # sockaddr_in with port and ip $ret, # The return value $msg, # Message to be echoed $finish_time, # Time ping should be finished $flush, # Whether socket needs to be disconnected $connect, # Whether socket needs to be connected $done, # Set to 1 when we are done pinging $rbits, # Read bits, filehandles for reading $nfound, # Number of ready filehandles found $from_saddr, # sockaddr_in of sender $from_msg, # Characters echoed by $host $from_port, # Port message was echoed from $from_ip # Packed IP number of sender ); $saddr = _pack_sockaddr_in($self->{port_num}, $ip); $self->{seq} = ($self->{seq} + 1) % 256; # Increment sequence $msg = chr($self->{seq}) . $self->{data}; # Add data if any socket($self->{fh}, $ip->{family}, SOCK_DGRAM, $self->{proto_num}) || croak("udp socket error - $!"); if (defined $self->{local_addr} && !CORE::bind($self->{fh}, _pack_sockaddr_in(0, $self->{local_addr}))) { croak("udp bind error - $!"); } $self->_setopts(); if ($self->{connected}) { if ($self->{connected} ne $saddr) { # Still connected to wrong destination. # Need to flush out the old one. $flush = 1; } } else { # Not connected yet. # Need to connect() before send() $connect = 1; } # Have to connect() and send() instead of sendto() # in order to pick up on the ECONNREFUSED setting # from recv() or double send() errno as utilized in # the concept by rdw @ perlmonks. See: # http://perlmonks.thepen.com/42898.html if ($flush) { # Need to socket() again to flush the descriptor # This will disconnect from the old saddr. socket($self->{fh}, $ip->{family}, SOCK_DGRAM, $self->{proto_num}); $self->_setopts(); } # Connect the socket if it isn't already connected # to the right destination. if ($flush || $connect) { connect($self->{fh}, $saddr); # Tie destination to socket $self->{connected} = $saddr; } send($self->{fh}, $msg, UDP_FLAGS); # Send it $rbits = ""; vec($rbits, $self->{fh}->fileno(), 1) = 1; $ret = 0; # Default to unreachable $done = 0; my $retrans = 0.01; my $factor = $self->{retrans}; $finish_time = &time() + $timeout; # Ping needs to be done by then while (!$done && $timeout > 0) { if ($factor > 1) { $timeout = $retrans if $timeout > $retrans; $retrans*= $factor; # Exponential backoff } $nfound = mselect((my $rout=$rbits), undef, undef, $timeout); # Wait for response my $why = $!; $timeout = $finish_time - &time(); # Get remaining time if (!defined($nfound)) # Hmm, a strange error { $ret = undef; $done = 1; } elsif ($nfound) # A packet is waiting { $from_msg = ""; $from_saddr = recv($self->{fh}, $from_msg, 1500, UDP_FLAGS); if (!$from_saddr) { # For example an unreachable host will make recv() fail. if (!$self->{econnrefused} && ($! == ECONNREFUSED || $! == ECONNRESET)) { # "Connection refused" means reachable # Good, continue $ret = 1; } $done = 1; } else { ($from_port, $from_ip) = _unpack_sockaddr_in($from_saddr, $ip->{family}); if (!$source_verify || (($from_ip eq $ip) && # Does the packet check out? ($from_port == $self->{port_num}) && ($from_msg eq $msg))) { $ret = 1; # It's a winner $done = 1; } } } elsif ($timeout <= 0) # Oops, timed out { $done = 1; } else { # Send another in case the last one dropped if (send($self->{fh}, $msg, UDP_FLAGS)) { # Another send worked? The previous udp packet # must have gotten lost or is still in transit. # Hopefully this new packet will arrive safely. } else { if (!$self->{econnrefused} && $! == ECONNREFUSED) { # "Connection refused" means reachable # Good, continue $ret = 1; } $done = 1; } } } return $ret; } # Description: Send a TCP SYN packet to host specified. sub ping_syn { my $self = shift; my $host = shift; my $ip = shift; my $start_time = shift; my $stop_time = shift; if ($syn_forking) { return $self->ping_syn_fork($host, $ip, $start_time, $stop_time); } my $fh = FileHandle->new(); my $saddr = _pack_sockaddr_in($self->{port_num}, $ip); # Create TCP socket if (!socket ($fh, $ip->{family}, SOCK_STREAM, $self->{proto_num})) { croak("tcp socket error - $!"); } if (defined $self->{local_addr} && !CORE::bind($fh, _pack_sockaddr_in(0, $self->{local_addr}))) { croak("tcp bind error - $!"); } $self->_setopts(); # Set O_NONBLOCK property on filehandle $self->socket_blocking_mode($fh, 0); # Attempt the non-blocking connect # by just sending the TCP SYN packet if (connect($fh, $saddr)) { # Non-blocking, yet still connected? # Must have connected very quickly, # or else it wasn't very non-blocking. #warn "WARNING: Nonblocking connect connected anyway? ($^O)"; } else { # Error occurred connecting. if ($! == EINPROGRESS || ($^O eq 'MSWin32' && $! == EWOULDBLOCK)) { # The connection is just still in progress. # This is the expected condition. } else { # Just save the error and continue on. # The ack() can check the status later. $self->{bad}->{$host} = $!; } } my $entry = [ $host, $ip, $fh, $start_time, $stop_time ]; $self->{syn}->{$fh->fileno} = $entry; if ($self->{stop_time} < $stop_time) { $self->{stop_time} = $stop_time; } vec($self->{wbits}, $fh->fileno, 1) = 1; return 1; } sub ping_syn_fork { my ($self, $host, $ip, $start_time, $stop_time) = @_; # Buggy Winsock API doesn't allow nonblocking connect. # Hence, if our OS is Windows, we need to create a separate # process to do the blocking connect attempt. my $pid = fork(); if (defined $pid) { if ($pid) { # Parent process my $entry = [ $host, $ip, $pid, $start_time, $stop_time ]; $self->{syn}->{$pid} = $entry; if ($self->{stop_time} < $stop_time) { $self->{stop_time} = $stop_time; } } else { # Child process my $saddr = _pack_sockaddr_in($self->{port_num}, $ip); # Create TCP socket if (!socket ($self->{fh}, $ip->{family}, SOCK_STREAM, $self->{proto_num})) { croak("tcp socket error - $!"); } if (defined $self->{local_addr} && !CORE::bind($self->{fh}, _pack_sockaddr_in(0, $self->{local_addr}))) { croak("tcp bind error - $!"); } $self->_setopts(); $!=0; # Try to connect (could take a long time) connect($self->{fh}, $saddr); # Notify parent of connect error status my $err = $!+0; my $wrstr = "$$ $err"; # Force to 16 chars including \n $wrstr .= " "x(15 - length $wrstr). "\n"; syswrite($self->{fork_wr}, $wrstr, length $wrstr); exit; } } else { # fork() failed? die "fork: $!"; } return 1; } # Description: Wait for TCP ACK from host specified # from ping_syn above. If no host is specified, wait # for TCP ACK from any of the hosts in the SYN queue. sub ack { my $self = shift; if ($self->{proto} eq "syn") { if ($syn_forking) { my @answer = $self->ack_unfork(shift); return wantarray ? @answer : $answer[0]; } my $wbits = ""; my $stop_time = 0; if (my $host = shift or $self->{host}) { # Host passed as arg or as option to new $host = $self->{host} unless defined $host; if (exists $self->{bad}->{$host}) { if (!$self->{econnrefused} && $self->{bad}->{ $host } && (($! = ECONNREFUSED)>0) && $self->{bad}->{ $host } eq "$!") { # "Connection refused" means reachable # Good, continue } else { # ECONNREFUSED means no good return (); } } my $host_fd = undef; foreach my $fd (keys %{ $self->{syn} }) { my $entry = $self->{syn}->{$fd}; if ($entry->[0] eq $host) { $host_fd = $fd; $stop_time = $entry->[4] || croak("Corrupted SYN entry for [$host]"); last; } } croak("ack called on [$host] without calling ping first!") unless defined $host_fd; vec($wbits, $host_fd, 1) = 1; } else { # No $host passed so scan all hosts # Use the latest stop_time $stop_time = $self->{stop_time}; # Use all the bits $wbits = $self->{wbits}; } while ($wbits !~ /^\0*\z/) { my $timeout = $stop_time - &time(); # Force a minimum of 10 ms timeout. $timeout = 0.01 if $timeout <= 0.01; my $winner_fd = undef; my $wout = $wbits; my $fd = 0; # Do "bad" fds from $wbits first while ($wout !~ /^\0*\z/) { if (vec($wout, $fd, 1)) { # Wipe it from future scanning. vec($wout, $fd, 1) = 0; if (my $entry = $self->{syn}->{$fd}) { if ($self->{bad}->{ $entry->[0] }) { $winner_fd = $fd; last; } } } $fd++; } if (defined($winner_fd) or my $nfound = mselect(undef, ($wout=$wbits), undef, $timeout)) { if (defined $winner_fd) { $fd = $winner_fd; } else { # Done waiting for one of the ACKs $fd = 0; # Determine which one while ($wout !~ /^\0*\z/ && !vec($wout, $fd, 1)) { $fd++; } } if (my $entry = $self->{syn}->{$fd}) { # Wipe it from future scanning. delete $self->{syn}->{$fd}; vec($self->{wbits}, $fd, 1) = 0; vec($wbits, $fd, 1) = 0; if (!$self->{econnrefused} && $self->{bad}->{ $entry->[0] } && (($! = ECONNREFUSED)>0) && $self->{bad}->{ $entry->[0] } eq "$!") { # "Connection refused" means reachable # Good, continue } elsif (getpeername($entry->[2])) { # Connection established to remote host # Good, continue } else { # TCP ACK will never come from this host # because there was an error connecting. # This should set $! to the correct error. my $char; sysread($entry->[2],$char,1); # Store the excuse why the connection failed. $self->{bad}->{$entry->[0]} = $!; if (!$self->{econnrefused} && (($! == ECONNREFUSED) || ($! == EAGAIN && $^O =~ /cygwin/i))) { # "Connection refused" means reachable # Good, continue } else { # No good, try the next socket... next; } } # Everything passed okay, return the answer return wantarray ? ($entry->[0], &time() - $entry->[3], $self->ntop($entry->[1])) : $entry->[0]; } else { warn "Corrupted SYN entry: unknown fd [$fd] ready!"; vec($wbits, $fd, 1) = 0; vec($self->{wbits}, $fd, 1) = 0; } } elsif (defined $nfound) { # Timed out waiting for ACK foreach my $fd (keys %{ $self->{syn} }) { if (vec($wbits, $fd, 1)) { my $entry = $self->{syn}->{$fd}; $self->{bad}->{$entry->[0]} = "Timed out"; vec($wbits, $fd, 1) = 0; vec($self->{wbits}, $fd, 1) = 0; delete $self->{syn}->{$fd}; } } } else { # Weird error occurred with select() warn("select: $!"); $self->{syn} = {}; $wbits = ""; } } } return (); } sub ack_unfork { my ($self,$host) = @_; my $stop_time = $self->{stop_time}; if ($host) { # Host passed as arg if (my $entry = $self->{good}->{$host}) { delete $self->{good}->{$host}; return ($entry->[0], &time() - $entry->[3], $self->ntop($entry->[1])); } } my $rbits = ""; my $timeout; if (keys %{ $self->{syn} }) { # Scan all hosts that are left vec($rbits, fileno($self->{fork_rd}), 1) = 1; $timeout = $stop_time - &time(); # Force a minimum of 10 ms timeout. $timeout = 0.01 if $timeout < 0.01; } else { # No hosts left to wait for $timeout = 0; } if ($timeout > 0) { my $nfound; while ( keys %{ $self->{syn} } and $nfound = mselect((my $rout=$rbits), undef, undef, $timeout)) { # Done waiting for one of the ACKs if (!sysread($self->{fork_rd}, $_, 16)) { # Socket closed, which means all children are done. return (); } my ($pid, $how) = split; if ($pid) { # Flush the zombie waitpid($pid, 0); if (my $entry = $self->{syn}->{$pid}) { # Connection attempt to remote host is done delete $self->{syn}->{$pid}; if (!$how || # If there was no error connecting (!$self->{econnrefused} && $how == ECONNREFUSED)) { # "Connection refused" means reachable if ($host && $entry->[0] ne $host) { # A good connection, but not the host we need. # Move it from the "syn" hash to the "good" hash. $self->{good}->{$entry->[0]} = $entry; # And wait for the next winner next; } return ($entry->[0], &time() - $entry->[3], $self->ntop($entry->[1])); } } else { # Should never happen die "Unknown ping from pid [$pid]"; } } else { die "Empty response from status socket?"; } } if (defined $nfound) { # Timed out waiting for ACK status } else { # Weird error occurred with select() warn("select: $!"); } } if (my @synners = keys %{ $self->{syn} }) { # Kill all the synners kill 9, @synners; foreach my $pid (@synners) { # Wait for the deaths to finish # Then flush off the zombie waitpid($pid, 0); } } $self->{syn} = {}; return (); } # Description: Tell why the ack() failed sub nack { my $self = shift; my $host = shift || croak('Usage> nack($failed_ack_host)'); return $self->{bad}->{$host} || undef; } # Description: Close the connection. sub close { my ($self) = @_; if ($self->{proto} eq "syn") { delete $self->{syn}; } elsif ($self->{proto} eq "tcp") { # The connection will already be closed } elsif ($self->{proto} eq "external") { # Nothing to close } else { $self->{fh}->close(); } } sub port_number { my $self = shift; if(@_) { $self->{port_num} = shift @_; $self->service_check(1); } return $self->{port_num}; } sub ntop { my($self, $ip) = @_; # Vista doesn't define a inet_ntop. It has InetNtop instead. # Not following ANSI... priceless. getnameinfo() is defined # for Windows 2000 and later, so that may be the choice. # Any port will work, even undef, but this will work for now. # Socket warns when undef is passed in, but it still works. my $port = getservbyname('echo', 'udp'); my $sockaddr = _pack_sockaddr_in($port, $ip); my ($error, $address) = getnameinfo($sockaddr, NI_NUMERICHOST); if($error) { croak $error; } return $address; } sub wakeonlan { my ($mac_addr, $host, $port) = @_; # use the discard service if $port not passed in if (! defined $host) { $host = '255.255.255.255' } if (! defined $port || $port !~ /^\d+$/ ) { $port = 9 } require IO::Socket::INET; my $sock = IO::Socket::INET->new(Proto=>'udp') || return undef; my $ip_addr = inet_aton($host); my $sock_addr = sockaddr_in($port, $ip_addr); $mac_addr =~ s/://g; my $packet = pack('C6H*', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, $mac_addr x 16); setsockopt($sock, SOL_SOCKET, SO_BROADCAST, 1); send($sock, $packet, 0, $sock_addr); $sock->close; return 1; } ######################################################## # DNS hostname resolution # return: # $h->{name} = host - as passed in # $h->{host} = host - as passed in without :port # $h->{port} = OPTIONAL - if :port, then value of port # $h->{addr} = resolved numeric address # $h->{addr_in} = aton/pton result # $h->{family} = AF_INET/6 ############################ sub _resolv { my ($self, $name, ) = @_; my %h; $h{name} = $name; my $family = $self->{family}; if (defined($self->{family_local})) { $family = $self->{family_local} } # START - host:port my $cnt = 0; # Count ":" $cnt++ while ($name =~ m/:/g); # 0 = hostname or IPv4 address if ($cnt == 0) { $h{host} = $name # 1 = IPv4 address with port } elsif ($cnt == 1) { ($h{host}, $h{port}) = split /:/, $name # >=2 = IPv6 address } elsif ($cnt >= 2) { #IPv6 with port - [2001::1]:port if ($name =~ /^\[.*\]:\d{1,5}$/) { ($h{host}, $h{port}) = split /:([^:]+)$/, $name # split after last : # IPv6 without port } else { $h{host} = $name } } # Clean up host $h{host} =~ s/\[//g; $h{host} =~ s/\]//g; # Clean up port if (defined($h{port}) && (($h{port} !~ /^\d{1,5}$/) || ($h{port} < 1) || ($h{port} > 65535))) { croak("Invalid port `$h{port}' in `$name'"); return undef; } # END - host:port # address check # new way if ($Socket::VERSION >= 1.94) { my %hints = ( family => $AF_UNSPEC, protocol => IPPROTO_TCP, flags => $AI_NUMERICHOST ); # numeric address, return my ($err, @getaddr) = Socket::getaddrinfo($h{host}, undef, \%hints); if (defined($getaddr[0])) { $h{addr} = $h{host}; $h{family} = $getaddr[0]->{family}; if ($h{family} == AF_INET) { (undef, $h{addr_in}, undef, undef) = Socket::unpack_sockaddr_in $getaddr[0]->{addr}; } else { (undef, $h{addr_in}, undef, undef) = Socket::unpack_sockaddr_in6 $getaddr[0]->{addr}; } return \%h } # old way } else { # numeric address, return my $ret = gethostbyname($h{host}); if (defined($ret) && (_inet_ntoa($ret) eq $h{host})) { $h{addr} = $h{host}; $h{addr_in} = $ret; $h{family} = AF_INET; return \%h } } # resolve # new way if ($Socket::VERSION >= 1.94) { my %hints = ( family => $family, protocol => IPPROTO_TCP ); my ($err, @getaddr) = Socket::getaddrinfo($h{host}, undef, \%hints); if (defined($getaddr[0])) { my ($err, $address) = Socket::getnameinfo($getaddr[0]->{addr}, $NI_NUMERICHOST); if (defined($address)) { $h{addr} = $address; $h{addr} =~ s/\%(.)*$//; # remove %ifID if IPv6 $h{family} = $getaddr[0]->{family}; if ($h{family} == AF_INET) { (undef, $h{addr_in}, undef, undef) = Socket::unpack_sockaddr_in $getaddr[0]->{addr}; } else { (undef, $h{addr_in}, undef, undef) = Socket::unpack_sockaddr_in6 $getaddr[0]->{addr}; } return \%h; } else { carp("getnameinfo($getaddr[0]->{addr}) failed - $err"); return undef; } } else { warn(sprintf("getaddrinfo($h{host},,%s) failed - $err", $family == AF_INET ? "AF_INET" : "AF_INET6")); return undef; } # old way } else { if ($family == $AF_INET6) { croak("Socket >= 1.94 required for IPv6 - found Socket $Socket::VERSION"); return undef; } my @gethost = gethostbyname($h{host}); if (defined($gethost[4])) { $h{addr} = inet_ntoa($gethost[4]); $h{addr_in} = $gethost[4]; $h{family} = AF_INET; return \%h } else { carp("gethostbyname($h{host}) failed - $^E"); return undef; } } return undef; } sub _pack_sockaddr_in($$) { my ($port, $ip, ) = @_; my $addr = ref($ip) eq "HASH" ? $ip->{addr_in} : $ip; if (length($addr) <= 4 ) { return Socket::pack_sockaddr_in($port, $addr); } else { return Socket::pack_sockaddr_in6($port, $addr); } } sub _unpack_sockaddr_in($;$) { my ($addr, $family, ) = @_; my ($port, $host); if ($family == AF_INET || (!defined($family) and length($addr) <= 16 )) { ($port, $host) = Socket::unpack_sockaddr_in($addr); } else { ($port, $host) = Socket::unpack_sockaddr_in6($addr); } return $port, $host } sub _inet_ntoa { my ($addr ) = @_; my $ret; if ($Socket::VERSION >= 1.94) { my ($err, $address) = Socket::getnameinfo($addr, $NI_NUMERICHOST); if (defined($address)) { $ret = $address; } else { carp("getnameinfo($addr) failed - $err"); } } else { $ret = inet_ntoa($addr) } return $ret } 1; __END__ =head1 NAME Net::Ping - check a remote host for reachability =head1 SYNOPSIS use Net::Ping; $p = Net::Ping->new(); print "$host is alive.\n" if $p->ping($host); $p->close(); $p = Net::Ping->new("icmp"); $p->bind($my_addr); # Specify source interface of pings foreach $host (@host_array) { print "$host is "; print "NOT " unless $p->ping($host, 2); print "reachable.\n"; sleep(1); } $p->close(); $p = Net::Ping->new("tcp", 2); # Try connecting to the www port instead of the echo port $p->port_number(scalar(getservbyname("http", "tcp"))); while ($stop_time > time()) { print "$host not reachable ", scalar(localtime()), "\n" unless $p->ping($host); sleep(300); } undef($p); # Like tcp protocol, but with many hosts $p = Net::Ping->new("syn"); $p->port_number(getservbyname("http", "tcp")); foreach $host (@host_array) { $p->ping($host); } while (($host,$rtt,$ip) = $p->ack) { print "HOST: $host [$ip] ACKed in $rtt seconds.\n"; } # High precision syntax (requires Time::HiRes) $p = Net::Ping->new(); $p->hires(); ($ret, $duration, $ip) = $p->ping($host, 5.5); printf("$host [ip: $ip] is alive (packet return time: %.2f ms)\n", 1000 * $duration) if $ret; $p->close(); # For backward compatibility print "$host is alive.\n" if pingecho($host); =head1 DESCRIPTION This module contains methods to test the reachability of remote hosts on a network. A ping object is first created with optional parameters, a variable number of hosts may be pinged multiple times and then the connection is closed. You may choose one of six different protocols to use for the ping. The "tcp" protocol is the default. Note that a live remote host may still fail to be pingable by one or more of these protocols. For example, www.microsoft.com is generally alive but not "icmp" pingable. With the "tcp" protocol the ping() method attempts to establish a connection to the remote host's echo port. If the connection is successfully established, the remote host is considered reachable. No data is actually echoed. This protocol does not require any special privileges but has higher overhead than the "udp" and "icmp" protocols. Specifying the "udp" protocol causes the ping() method to send a udp packet to the remote host's echo port. If the echoed packet is received from the remote host and the received packet contains the same data as the packet that was sent, the remote host is considered reachable. This protocol does not require any special privileges. It should be borne in mind that, for a udp ping, a host will be reported as unreachable if it is not running the appropriate echo service. For Unix-like systems see L for more information. If the "icmp" protocol is specified, the ping() method sends an icmp echo message to the remote host, which is what the UNIX ping program does. If the echoed message is received from the remote host and the echoed information is correct, the remote host is considered reachable. Specifying the "icmp" protocol requires that the program be run as root or that the program be setuid to root. If the "external" protocol is specified, the ping() method attempts to use the C module to ping the remote host. C interfaces with your system's default C utility to perform the ping, and generally produces relatively accurate results. If C if not installed on your system, specifying the "external" protocol will result in an error. If the "syn" protocol is specified, the ping() method will only send a TCP SYN packet to the remote host then immediately return. If the syn packet was sent successfully, it will return a true value, otherwise it will return false. NOTE: Unlike the other protocols, the return value does NOT determine if the remote host is alive or not since the full TCP three-way handshake may not have completed yet. The remote host is only considered reachable if it receives a TCP ACK within the timeout specified. To begin waiting for the ACK packets, use the ack() method as explained below. Use the "syn" protocol instead the "tcp" protocol to determine reachability of multiple destinations simultaneously by sending parallel TCP SYN packets. It will not block while testing each remote host. demo/fping is provided in this distribution to demonstrate the "syn" protocol as an example. This protocol does not require any special privileges. =head2 Functions =over 4 =item Net::Ping->new([proto, timeout, bytes, device, tos, ttl, family, host, port, bind, gateway, retrans, pingstring, source_verify econnrefused dontfrag IPV6_USE_MIN_MTU IPV6_RECVPATHMTU]) Create a new ping object. All of the parameters are optional and can be passed as hash ref. All options besides the first 7 must be passed as hash ref. C specifies the protocol to use when doing a ping. The current choices are "tcp", "udp", "icmp", "icmpv6", "stream", "syn", or "external". The default is "tcp". If a C in seconds is provided, it is used when a timeout is not given to the ping() method (below). The timeout must be greater than 0 and the default, if not specified, is 5 seconds. If the number of data bytes (C) is given, that many data bytes are included in the ping packet sent to the remote host. The number of data bytes is ignored if the protocol is "tcp". The minimum (and default) number of data bytes is 1 if the protocol is "udp" and 0 otherwise. The maximum number of data bytes that can be specified is 1024. If C is given, this device is used to bind the source endpoint before sending the ping packet. I believe this only works with superuser privileges and with udp and icmp protocols at this time. If is given, this ToS is configured into the socket. For icmp, C can be specified to set the TTL of the outgoing packet. Valid C values for IPv4: 4, v4, ip4, ipv4, AF_INET (constant) Valid C values for IPv6: 6, v6, ip6, ipv6, AF_INET6 (constant) The C argument implicitly specifies the family if the family argument is not given. The C argument is only valid for a udp, tcp or stream ping, and will not do what you think it does. ping returns true when we get a "Connection refused"! The default is the echo port. The C argument specifies the local_addr to bind to. By specifying a bind argument you don't need the bind method. The C argument is only valid for IPv6, and requires a IPv6 address. The C argument the exponential backoff rate, default 1.2. It matches the $def_factor global. The C argument sets the IP_DONTFRAG bit, but note that IP_DONTFRAG is not yet defined by Socket, and not available on many systems. Then it is ignored. On linux it also sets IP_MTU_DISCOVER to IP_PMTUDISC_DO but need we don't chunk oversized packets. You need to set $data_size manually. =item $p->ping($host [, $timeout [, $family]]); Ping the remote host and wait for a response. $host can be either the hostname or the IP number of the remote host. The optional timeout must be greater than 0 seconds and defaults to whatever was specified when the ping object was created. Returns a success flag. If the hostname cannot be found or there is a problem with the IP number, the success flag returned will be undef. Otherwise, the success flag will be 1 if the host is reachable and 0 if it is not. For most practical purposes, undef and 0 and can be treated as the same case. In array context, the elapsed time as well as the string form of the ip the host resolved to are also returned. The elapsed time value will be a float, as returned by the Time::HiRes::time() function, if hires() has been previously called, otherwise it is returned as an integer. =item $p->source_verify( { 0 | 1 } ); Allows source endpoint verification to be enabled or disabled. This is useful for those remote destinations with multiples interfaces where the response may not originate from the same endpoint that the original destination endpoint was sent to. This only affects udp and icmp protocol pings. This is enabled by default. =item $p->service_check( { 0 | 1 } ); Set whether or not the connect behavior should enforce remote service availability as well as reachability. Normally, if the remote server reported ECONNREFUSED, it must have been reachable because of the status packet that it reported. With this option enabled, the full three-way tcp handshake must have been established successfully before it will claim it is reachable. NOTE: It still does nothing more than connect and disconnect. It does not speak any protocol (i.e., HTTP or FTP) to ensure the remote server is sane in any way. The remote server CPU could be grinding to a halt and unresponsive to any clients connecting, but if the kernel throws the ACK packet, it is considered alive anyway. To really determine if the server is responding well would be application specific and is beyond the scope of Net::Ping. For udp protocol, enabling this option demands that the remote server replies with the same udp data that it was sent as defined by the udp echo service. This affects the "udp", "tcp", and "syn" protocols. This is disabled by default. =item $p->tcp_service_check( { 0 | 1 } ); Deprecated method, but does the same as service_check() method. =item $p->hires( { 0 | 1 } ); With 1 causes this module to use Time::HiRes module, allowing milliseconds to be returned by subsequent calls to ping(). =item $p->time The current time, hires or not. =item $p->socket_blocking_mode( $fh, $mode ); Sets or clears the O_NONBLOCK flag on a file handle. =item $p->IPV6_USE_MIN_MTU With argument sets the option. Without returns the option value. =item $p->IPV6_RECVPATHMTU Notify an according IPv6 MTU. With argument sets the option. Without returns the option value. =item $p->IPV6_HOPLIMIT With argument sets the option. Without returns the option value. =item $p->IPV6_REACHCONF I Sets ipv6 reachability IPV6_REACHCONF was removed in RFC3542. ping6 -R supports it. IPV6_REACHCONF requires root/admin permissions. With argument sets the option. Without returns the option value. Not yet implemented. =item $p->bind($local_addr); Sets the source address from which pings will be sent. This must be the address of one of the interfaces on the local host. $local_addr may be specified as a hostname or as a text IP address such as "192.168.1.1". If the protocol is set to "tcp", this method may be called any number of times, and each call to the ping() method (below) will use the most recent $local_addr. If the protocol is "icmp" or "udp", then bind() must be called at most once per object, and (if it is called at all) must be called before the first call to ping() for that object. The bind() call can be omitted when specifying the C option to new(). =item $p->open($host); When you are using the "stream" protocol, this call pre-opens the tcp socket. It's only necessary to do this if you want to provide a different timeout when creating the connection, or remove the overhead of establishing the connection from the first ping. If you don't call C, the connection is automatically opened the first time C is called. This call simply does nothing if you are using any protocol other than stream. The $host argument can be omitted when specifying the C option to new(). =item $p->ack( [ $host ] ); When using the "syn" protocol, use this method to determine the reachability of the remote host. This method is meant to be called up to as many times as ping() was called. Each call returns the host (as passed to ping()) that came back with the TCP ACK. The order in which the hosts are returned may not necessarily be the same order in which they were SYN queued using the ping() method. If the timeout is reached before the TCP ACK is received, or if the remote host is not listening on the port attempted, then the TCP connection will not be established and ack() will return undef. In list context, the host, the ack time, and the dotted ip string will be returned instead of just the host. If the optional $host argument is specified, the return value will be pertaining to that host only. This call simply does nothing if you are using any protocol other than syn. When new() had a host option, this host will be used. Without host argument, all hosts are scanned. =item $p->nack( $failed_ack_host ); The reason that host $failed_ack_host did not receive a valid ACK. Useful to find out why when ack( $fail_ack_host ) returns a false value. =item $p->ack_unfork($host) The variant called by ack() with the syn protocol and $syn_forking enabled. =item $p->ping_icmp([$host, $timeout, $family]) The ping() method used with the icmp protocol. =item $p->ping_icmpv6([$host, $timeout, $family]) I The ping() method used with the icmpv6 protocol. =item $p->ping_stream([$host, $timeout, $family]) The ping() method used with the stream protocol. Perform a stream ping. If the tcp connection isn't already open, it opens it. It then sends some data and waits for a reply. It leaves the stream open on exit. =item $p->ping_syn([$host, $ip, $start_time, $stop_time]) The ping() method used with the syn protocol. Sends a TCP SYN packet to host specified. =item $p->ping_syn_fork([$host, $timeout, $family]) The ping() method used with the forking syn protocol. =item $p->ping_tcp([$host, $timeout, $family]) The ping() method used with the tcp protocol. =item $p->ping_udp([$host, $timeout, $family]) The ping() method used with the udp protocol. Perform a udp echo ping. Construct a message of at least the one-byte sequence number and any additional data bytes. Send the message out and wait for a message to come back. If we get a message, make sure all of its parts match. If they do, we are done. Otherwise go back and wait for the message until we run out of time. Return the result of our efforts. =item $p->ping_external([$host, $timeout, $family]) The ping() method used with the external protocol. Uses Net::Ping::External to do an external ping. =item $p->tcp_connect([$ip, $timeout]) Initiates a TCP connection, for a tcp ping. =item $p->tcp_echo([$ip, $timeout, $pingstring]) Performs a TCP echo. It writes the given string to the socket and then reads it back. It returns 1 on success, 0 on failure. =item $p->close(); Close the network connection for this ping object. The network connection is also closed by "undef $p". The network connection is automatically closed if the ping object goes out of scope (e.g. $p is local to a subroutine and you leave the subroutine). =item $p->port_number([$port_number]) When called with a port number, the port number used to ping is set to $port_number rather than using the echo port. It also has the effect of calling C<$p-Eservice_check(1)> causing a ping to return a successful response only if that specific port is accessible. This function returns the value of the port that C will connect to. =item $p->mselect A select() wrapper that compensates for platform peculiarities. =item $p->ntop Platform abstraction over inet_ntop() =item $p->checksum($msg) Do a checksum on the message. Basically sum all of the short words and fold the high order bits into the low order bits. =item $p->icmp_result Returns a list of addr, type, subcode. =item pingecho($host [, $timeout]); To provide backward compatibility with the previous version of Net::Ping, a pingecho() subroutine is available with the same functionality as before. pingecho() uses the tcp protocol. The return values and parameters are the same as described for the ping() method. This subroutine is obsolete and may be removed in a future version of Net::Ping. =item wakeonlan($mac, [$host, [$port]]) Emit the popular wake-on-lan magic udp packet to wake up a local device. See also L, but this has the mac address as 1st arg. $host should be the local gateway. Without it will broadcast. Default host: '255.255.255.255' Default port: 9 perl -MNet::Ping=wakeonlan -e'wakeonlan "e0:69:95:35:68:d2"' =back =head1 NOTES There will be less network overhead (and some efficiency in your program) if you specify either the udp or the icmp protocol. The tcp protocol will generate 2.5 times or more traffic for each ping than either udp or icmp. If many hosts are pinged frequently, you may wish to implement a small wait (e.g. 25ms or more) between each ping to avoid flooding your network with packets. The icmp and icmpv6 protocols requires that the program be run as root or that it be setuid to root. The other protocols do not require special privileges, but not all network devices implement tcp or udp echo. Local hosts should normally respond to pings within milliseconds. However, on a very congested network it may take up to 3 seconds or longer to receive an echo packet from the remote host. If the timeout is set too low under these conditions, it will appear that the remote host is not reachable (which is almost the truth). Reachability doesn't necessarily mean that the remote host is actually functioning beyond its ability to echo packets. tcp is slightly better at indicating the health of a system than icmp because it uses more of the networking stack to respond. Because of a lack of anything better, this module uses its own routines to pack and unpack ICMP packets. It would be better for a separate module to be written which understands all of the different kinds of ICMP packets. =head1 INSTALL The latest source tree is available via git: git clone https://github.com/rurban/net-ping.git Net-Ping cd Net-Ping The tarball can be created as follows: perl Makefile.PL ; make ; make dist The latest Net::Ping releases are included in cperl and perl5. =head1 BUGS For a list of known issues, visit: L To report a new bug, visit: L (stale) or call: perlbug resp.: cperlbug =head1 AUTHORS Current maintainers: perl11 (for cperl, with IPv6 support and more) p5p (for perl5) Previous maintainers: bbb@cpan.org (Rob Brown) Steve Peters External protocol: colinm@cpan.org (Colin McMillen) Stream protocol: bronson@trestle.com (Scott Bronson) Wake-on-lan: 1999-2003 Clinton Wong Original pingecho(): karrer@bernina.ethz.ch (Andreas Karrer) pmarquess@bfsec.bt.co.uk (Paul Marquess) Original Net::Ping author: mose@ns.ccsn.edu (Russell Mosemann) =head1 COPYRIGHT Copyright (c) 2016, cPanel Inc. All rights reserved. Copyright (c) 2012, Steve Peters. All rights reserved. Copyright (c) 2002-2003, Rob Brown. All rights reserved. Copyright (c) 2001, Colin McMillen. All rights reserved. This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. =cut PKp0]y4 netent.pmnu[package Net::netent; use strict; use 5.006_001; our $VERSION = '1.00'; our(@EXPORT, @EXPORT_OK, %EXPORT_TAGS); BEGIN { use Exporter (); @EXPORT = qw(getnetbyname getnetbyaddr getnet); @EXPORT_OK = qw( $n_name @n_aliases $n_addrtype $n_net ); %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] ); } use vars @EXPORT_OK; # Class::Struct forbids use of @ISA sub import { goto &Exporter::import } use Class::Struct qw(struct); struct 'Net::netent' => [ name => '$', aliases => '@', addrtype => '$', net => '$', ]; sub populate (@) { return unless @_; my $nob = new(); $n_name = $nob->[0] = $_[0]; @n_aliases = @{ $nob->[1] } = split ' ', $_[1]; $n_addrtype = $nob->[2] = $_[2]; $n_net = $nob->[3] = $_[3]; return $nob; } sub getnetbyname ($) { populate(CORE::getnetbyname(shift)) } sub getnetbyaddr ($;$) { my ($net, $addrtype); $net = shift; require Socket if @_; $addrtype = @_ ? shift : Socket::AF_INET(); populate(CORE::getnetbyaddr($net, $addrtype)) } sub getnet($) { if ($_[0] =~ /^\d+(?:\.\d+(?:\.\d+(?:\.\d+)?)?)?$/) { require Socket; &getnetbyaddr(Socket::inet_aton(shift)); } else { &getnetbyname; } } 1; __END__ =head1 NAME Net::netent - by-name interface to Perl's built-in getnet*() functions =head1 SYNOPSIS use Net::netent qw(:FIELDS); getnetbyname("loopback") or die "bad net"; printf "%s is %08X\n", $n_name, $n_net; use Net::netent; $n = getnetbyname("loopback") or die "bad net"; { # there's gotta be a better way, eh? @bytes = unpack("C4", pack("N", $n->net)); shift @bytes while @bytes && $bytes[0] == 0; } printf "%s is %08X [%d.%d.%d.%d]\n", $n->name, $n->net, @bytes; =head1 DESCRIPTION This module's default exports override the core getnetbyname() and getnetbyaddr() functions, replacing them with versions that return "Net::netent" objects. This object has methods that return the similarly named structure field name from the C's netent structure from F; namely name, aliases, addrtype, and net. The aliases method returns an array reference, the rest scalars. You may also import all the structure fields directly into your namespace as regular variables using the :FIELDS import tag. (Note that this still overrides your core functions.) Access these fields as variables named with a preceding C. Thus, C<$net_obj-Ename()> corresponds to $n_name if you import the fields. Array references are available as regular array variables, so for example C<@{ $net_obj-Ealiases() }> would be simply @n_aliases. The getnet() function is a simple front-end that forwards a numeric argument to getnetbyaddr(), and the rest to getnetbyname(). To access this functionality without the core overrides, pass the C an empty import list, and then access function functions with their full qualified names. On the other hand, the built-ins are still available via the C pseudo-package. =head1 EXAMPLES The getnet() functions do this in the Perl core: sv_setiv(sv, (I32)nent->n_net); The gethost() functions do this in the Perl core: sv_setpvn(sv, hent->h_addr, len); That means that the address comes back in binary for the host functions, and as a regular perl integer for the net ones. This seems a bug, but here's how to deal with it: use strict; use Socket; use Net::netent; @ARGV = ('loopback') unless @ARGV; my($n, $net); for $net ( @ARGV ) { unless ($n = getnetbyname($net)) { warn "$0: no such net: $net\n"; next; } printf "\n%s is %s%s\n", $net, lc($n->name) eq lc($net) ? "" : "*really* ", $n->name; print "\taliases are ", join(", ", @{$n->aliases}), "\n" if @{$n->aliases}; # this is stupid; first, why is this not in binary? # second, why am i going through these convolutions # to make it looks right { my @a = unpack("C4", pack("N", $n->net)); shift @a while @a && $a[0] == 0; printf "\taddr is %s [%d.%d.%d.%d]\n", $n->net, @a; } if ($n = getnetbyaddr($n->net)) { if (lc($n->name) ne lc($net)) { printf "\tThat addr reverses to net %s!\n", $n->name; $net = $n->name; redo; } } } =head1 NOTE While this class is currently implemented using the Class::Struct module to build a struct-like class, you shouldn't rely upon this. =head1 AUTHOR Tom Christiansen PKR1]Wp{{ SSLeay.podnu[=encoding utf-8 =head1 NAME Net::SSLeay - Perl extension for using OpenSSL =head1 SYNOPSIS use Net::SSLeay qw(get_https post_https sslcat make_headers make_form); ($page) = get_https('www.bacus.pt', 443, '/'); # Case 1 ($page, $response, %reply_headers) = get_https('www.bacus.pt', 443, '/', # Case 2 make_headers(User-Agent => 'Cryptozilla/5.0b1', Referer => 'https://www.bacus.pt' )); ($page, $result, %headers) = # Case 2b = get_https('www.bacus.pt', 443, '/protected.html', make_headers(Authorization => 'Basic ' . MIME::Base64::encode("$user:$pass",'')) ); ($page, $response, %reply_headers) = post_https('www.bacus.pt', 443, '/foo.cgi', '', # Case 3 make_form(OK => '1', name => 'Sampo' )); $reply = sslcat($host, $port, $request); # Case 4 ($reply, $err, $server_cert) = sslcat($host, $port, $request); # Case 5 $Net::SSLeay::trace = 2; # 0=no debugging, 1=ciphers, 2=trace, 3=dump data Net::SSLeay::initialize(); # Initialize ssl library once =head1 DESCRIPTION L module contains perl bindings to openssl (L) library. B L cannot be built with pre-0.9.3 openssl. It is strongly recommended to use at least 0.9.7 (as older versions are not tested during development). Some low level API functions may be available with certain openssl versions. It is compatible with OpenSSL 1.0 and 1.1. Some functions are not available under OpenSSL 1.1. L module basically comprise of: =over =item * High level functions for accessing web servers (by using HTTP/HTTPS) =item * Low level API (mostly mapped 1:1 to openssl's C functions) =item * Convenience functions (related to low level API but with more perl friendly interface) =back There is also a related module called L included in this distribution that you might want to use instead. It has its own pod documentation. =head2 High level functions for accessing web servers This module offers some high level convenience functions for accessing web pages on SSL servers (for symmetry, the same API is offered for accessing http servers, too), an C function for writing your own clients, and finally access to the SSL api of the SSLeay/OpenSSL package so you can write servers or clients for more complicated applications. For high level functions it is most convenient to import them into your main namespace as indicated in the synopsis. =head3 Basic set of functions =over =item * get_https =item * post_https =item * put_https =item * head_https =item * do_https =item * sslcat =item * https_cat =item * make_form =item * make_headers =back B demonstrates the typical invocation of get_https() to fetch an HTML page from secure server. The first argument provides the hostname or IP in dotted decimal notation of the remote server to contact. The second argument is the TCP port at the remote end (your own port is picked arbitrarily from high numbered ports as usual for TCP). The third argument is the URL of the page without the host name part. If in doubt consult the HTTP specifications at L. B demonstrates full fledged use of C. As can be seen, C parses the response and response headers and returns them as a list, which can be captured in a hash for later reference. Also a fourth argument to C is used to insert some additional headers in the request. C is a function that will convert a list or hash to such headers. By default C supplies C (to make virtual hosting easy) and C (reportedly needed by IIS) headers. B demonstrates how to get a password protected page. Refer to the HTTP protocol specifications for further details (e.g. RFC-2617). B invokes C to submit a HTML/CGI form to a secure server. The first four arguments are equal to C (note that the empty string (C<''>) is passed as header argument). The fifth argument is the contents of the form formatted according to CGI specification. Do not post UTF-8 data as content: use utf8::downgrade first. In this case the helper function C is used to do the formatting, but you could pass any string. C automatically adds C and C headers to the request. B shows the fundamental C function (inspired in spirit by the C utility :-). It's your swiss army knife that allows you to easily contact servers, send some data, and then get the response. You are responsible for formatting the data and parsing the response - C is just a transport. B is a full invocation of C which allows the return of errors as well as the server (peer) certificate. The C<$trace> global variable can be used to control the verbosity of the high level functions. Level 0 guarantees silence, level 1 (the default) only emits error messages. =head3 Alternate versions of high-level API =over =item * get_https3 =item * post_https3 =item * put_https3 =item * get_https4 =item * post_https4 =item * put_https4 =back The above mentioned functions actually return the response headers as a list, which only gets converted to hash upon assignment (this assignment looses information if the same header occurs twice, as may be the case with cookies). There are also other variants of the functions that return unprocessed headers and that return a reference to a hash. ($page, $response, @headers) = get_https('www.bacus.pt', 443, '/'); for ($i = 0; $i < $#headers; $i+=2) { print "$headers[$i] = " . $headers[$i+1] . "\n"; } ($page, $response, $headers, $server_cert) = get_https3('www.bacus.pt', 443, '/'); print "$headers\n"; ($page, $response, $headers_ref) = get_https4('www.bacus.pt', 443, '/'); for $k (sort keys %{$headers_ref}) { for $v (@{$$headers_ref{$k}}) { print "$k = $v\n"; } } All of the above code fragments accomplish the same thing: display all values of all headers. The API functions ending in "3" return the headers simply as a scalar string and it is up to the application to split them up. The functions ending in "4" return a reference to a hash of arrays (see L and L if you are not familiar with complex perl data structures). To access a single value of such a header hash you would do something like print $$headers_ref{COOKIE}[0]; Variants 3 and 4 also allow you to discover the server certificate in case you would like to store or display it, e.g. ($p, $resp, $hdrs, $server_cert) = get_https3('www.bacus.pt', 443, '/'); if (!defined($server_cert) || ($server_cert == 0)) { warn "Subject Name: undefined, Issuer Name: undefined"; } else { warn 'Subject Name: ' . Net::SSLeay::X509_NAME_oneline( Net::SSLeay::X509_get_subject_name($server_cert)) . 'Issuer Name: ' . Net::SSLeay::X509_NAME_oneline( Net::SSLeay::X509_get_issuer_name($server_cert)); } Beware that this method only allows after the fact verification of the certificate: by the time C has returned the https request has already been sent to the server, whether you decide to trust it or not. To do the verification correctly you must either employ the OpenSSL certificate verification framework or use the lower level API to first connect and verify the certificate and only then send the http data. See the implementation of C for guidance on how to do this. =head3 Using client certificates Secure web communications are encrypted using symmetric crypto keys exchanged using encryption based on the certificate of the server. Therefore in all SSL connections the server must have a certificate. This serves both to authenticate the server to the clients and to perform the key exchange. Sometimes it is necessary to authenticate the client as well. Two options are available: HTTP basic authentication and a client side certificate. The basic authentication over HTTPS is actually quite safe because HTTPS guarantees that the password will not travel in the clear. Never-the-less, problems like easily guessable passwords remain. The client certificate method involves authentication of the client at the SSL level using a certificate. For this to work, both the client and the server have certificates (which typically are different) and private keys. The API functions outlined above accept additional arguments that allow one to supply the client side certificate and key files. The format of these files is the same as used for server certificates and the caveat about encrypting private keys applies. ($page, $result, %headers) = # 2c = get_https('www.bacus.pt', 443, '/protected.html', make_headers(Authorization => 'Basic ' . MIME::Base64::encode("$user:$pass",'')), '', $mime_type6, $path_to_crt7, $path_to_key8); ($page, $response, %reply_headers) = post_https('www.bacus.pt', 443, '/foo.cgi', # 3b make_headers('Authorization' => 'Basic ' . MIME::Base64::encode("$user:$pass",'')), make_form(OK => '1', name => 'Sampo'), $mime_type6, $path_to_crt7, $path_to_key8); B demonstrates getting a password protected page that also requires a client certificate, i.e. it is possible to use both authentication methods simultaneously. B is a full blown POST to a secure server that requires both password authentication and a client certificate, just like in case 2c. Note: The client will not send a certificate unless the server requests one. This is typically achieved by setting the verify mode to C on the server: Net::SSLeay::set_verify(ssl, Net::SSLeay::VERIFY_PEER, 0); See C for a full description. =head3 Working through a web proxy =over =item * set_proxy =back C can use a web proxy to make its connections. You need to first set the proxy host and port using C and then just use the normal API functions, e.g: Net::SSLeay::set_proxy('gateway.myorg.com', 8080); ($page) = get_https('www.bacus.pt', 443, '/'); If your proxy requires authentication, you can supply a username and password as well Net::SSLeay::set_proxy('gateway.myorg.com', 8080, 'joe', 'salainen'); ($page, $result, %headers) = = get_https('www.bacus.pt', 443, '/protected.html', make_headers(Authorization => 'Basic ' . MIME::Base64::encode("susie:pass",'')) ); This example demonstrates the case where we authenticate to the proxy as C<"joe"> and to the final web server as C<"susie">. Proxy authentication requires the C module to work. =head3 HTTP (without S) API =over =item * get_http =item * post_http =item * tcpcat =item * get_httpx =item * post_httpx =item * tcpxcat =back Over the years it has become clear that it would be convenient to use the light-weight flavour API of C for normal HTTP as well (see C for the heavy-weight object-oriented approach). In fact it would be nice to be able to flip https on and off on the fly. Thus regular HTTP support was evolved. use Net::SSLeay qw(get_http post_http tcpcat get_httpx post_httpx tcpxcat make_headers make_form); ($page, $result, %headers) = get_http('www.bacus.pt', 443, '/protected.html', make_headers(Authorization => 'Basic ' . MIME::Base64::encode("$user:$pass",'')) ); ($page, $response, %reply_headers) = post_http('www.bacus.pt', 443, '/foo.cgi', '', make_form(OK => '1', name => 'Sampo' )); ($reply, $err) = tcpcat($host, $port, $request); ($page, $result, %headers) = get_httpx($usessl, 'www.bacus.pt', 443, '/protected.html', make_headers(Authorization => 'Basic ' . MIME::Base64::encode("$user:$pass",'')) ); ($page, $response, %reply_headers) = post_httpx($usessl, 'www.bacus.pt', 443, '/foo.cgi', '', make_form(OK => '1', name => 'Sampo' )); ($reply, $err, $server_cert) = tcpxcat($usessl, $host, $port, $request); As can be seen, the C<"x"> family of APIs takes as the first argument a flag which indicates whether SSL is used or not. =head2 Certificate verification and Certificate Revocation Lists (CRLs) OpenSSL supports the ability to verify peer certificates. It can also optionally check the peer certificate against a Certificate Revocation List (CRL) from the certificates issuer. A CRL is a file, created by the certificate issuer that lists all the certificates that it previously signed, but which it now revokes. CRLs are in PEM format. You can enable C checking like this: &Net::SSLeay::X509_STORE_set_flags (&Net::SSLeay::CTX_get_cert_store($ssl), &Net::SSLeay::X509_V_FLAG_CRL_CHECK); After setting this flag, if OpenSSL checks a peer's certificate, then it will attempt to find a CRL for the issuer. It does this by looking for a specially named file in the search directory specified by CTX_load_verify_locations. CRL files are named with the hash of the issuer's subject name, followed by C<.r0>, C<.r1> etc. For example C, C. It will read all the .r files for the issuer, and then check for a revocation of the peer certificate in all of them. (You can also force it to look in a specific named CRL file., see below). You can find out the hash of the issuer subject name in a CRL with openssl crl -in crl.pem -hash -noout If the peer certificate does not pass the revocation list, or if no CRL is found, then the handshaking fails with an error. You can also force OpenSSL to look for CRLs in one or more arbitrarily named files. my $bio = Net::SSLeay::BIO_new_file($crlfilename, 'r'); my $crl = Net::SSLeay::PEM_read_bio_X509_CRL($bio); if ($crl) { Net::SSLeay::X509_STORE_add_crl( Net::SSLeay::CTX_get_cert_store($ssl, $crl) ); } else { error reading CRL.... } Usually the URLs where you can download the CRLs is contained in the certificate itself and you can extract them with my @url = Net::SSLeay::P_X509_get_crl_distribution_points($cert) But there is no automatic downloading of the CRLs and often these CRLs are too huge to just download them to verify a single certificate. Also, these CRLs are often in DER format which you need to convert to PEM before you can use it: openssl crl -in crl.der -inform der -out crl.pem So as an alternative for faster and timely revocation checks you better use the Online Status Revocation Protocol (OCSP). =head2 Certificate verification and Online Status Revocation Protocol (OCSP) While checking for revoked certificates is possible and fast with Certificate Revocation Lists, you need to download the complete and often huge list before you can verify a single certificate. A faster way is to ask the CA to check the revocation of just a single or a few certificates using OCSP. Basically you generate for each certificate an OCSP_CERTID based on the certificate itself and its issuer, put the ids togetether into an OCSP_REQUEST and send the request to the URL given in the certificate. As a result you get back an OCSP_RESPONSE and need to check the status of the response, check that it is valid (e.g. signed by the CA) and finally extract the information about each OCSP_CERTID to find out if the certificate is still valid or got revoked. With Net::SSLeay this can be done like this: # get id(s) for given certs, like from get_peer_certificate # or get_peer_cert_chain. This will croak if # - one tries to make an OCSP_CERTID for a self-signed certificate # - the issuer of the certificate cannot be found in the SSL objects # store, nor in the current certificate chain my $cert = Net::SSLeay::get_peer_certificate($ssl); my $id = eval { Net::SSLeay::OCSP_cert2ids($ssl,$cert) }; die "failed to make OCSP_CERTID: $@" if $@; # create OCSP_REQUEST from id(s) # Multiple can be put into the same request, if the same OCSP responder # is responsible for them. my $req = Net::SSLeay::OCSP_ids2req($id); # determine URI of OCSP responder my $uri = Net::SSLeay::P_X509_get_ocsp_uri($cert); # Send stringified OCSP_REQUEST with POST to $uri. # We can ignore certificate verification for https, because the OCSP # response itself is signed. my $ua = HTTP::Tiny->new(verify_SSL => 0); my $res = $ua->request( 'POST',$uri, { headers => { 'Content-type' => 'application/ocsp-request' }, content => Net::SSLeay::i2d_OCSP_REQUEST($req) }); my $content = $res && $res->{success} && $res->{content} or die "query failed"; # Extract OCSP_RESPONSE. # this will croak if the string is not an OCSP_RESPONSE my $resp = eval { Net::SSLeay::d2i_OCSP_RESPONSE($content) }; # Check status of response. my $status = Net::SSLeay::OCSP_response_status($resp); if ($status != Net::SSLeay::OCSP_RESPONSE_STATUS_SUCCESSFUL()) die "OCSP response failed: ". Net::SSLeay::OCSP_response_status_str($status); } # Verify signature of response and if nonce matches request. # This will croak if there is a nonce in the response, but it does not match # the request. It will return false if the signature could not be verified, # in which case details can be retrieved with Net::SSLeay::ERR_get_error. # It will not complain if the response does not contain a nonce, which is # usually the case with pre-signed responses. if ( ! eval { Net::SSLeay::OCSP_response_verify($ssl,$resp,$req) }) { die "OCSP response verification failed"; } # Extract information from OCSP_RESPONSE for each of the ids. # If called in scalar context it will return the time (as time_t), when the # next update is due (minimum of all successful responses inside $resp). It # will croak on the following problems: # - response is expired or not yet valid # - no response for given OCSP_CERTID # - certificate status is not good (e.g. revoked or unknown) if ( my $nextupd = eval { Net::SSLeay::OCSP_response_results($resp,$id) }) { warn "certificate is valid, next update in ". ($nextupd-time())." seconds\n"; } else { die "certificate is not valid: $@"; } # But in array context it will return detailed information about each given # OCSP_CERTID instead croaking on errors: # if no @ids are given it will return information about all single responses # in the OCSP_RESPONSE my @results = Net::SSLeay::OCSP_response_results($resp,@ids); for my $r (@results) { print Dumper($r); # @results are in the same order as the @ids and contain: # $r->[0] - OCSP_CERTID # $r->[1] - undef if no error (certificate good) OR error message as string # $r->[2] - hash with details: # thisUpdate - time_t of this single response # nextUpdate - time_t when update is expected # statusType - integer: # V_OCSP_CERTSTATUS_GOOD(0) # V_OCSP_CERTSTATUS_REVOKED(1) # V_OCSP_CERTSTATUS_UNKNOWN(2) # revocationTime - time_t (only if revoked) # revocationReason - integer (only if revoked) # revocationReason_str - reason as string (only if revoked) } To further speed up certificate revocation checking one can use a TLS extension to instruct the server to staple the OCSP response: # set TLS extension before doing SSL_connect Net::SSLeay::set_tlsext_status_type($ssl, Net::SSLeay::TLSEXT_STATUSTYPE_ocsp()); # setup callback to verify OCSP response my $cert_valid = undef; Net::SSLeay::CTX_set_tlsext_status_cb($context,sub { my ($ssl,$resp) = @_; if (!$resp) { # Lots of servers don't return an OCSP response. # In this case we must check the OCSP status outside the SSL # handshake. warn "server did not return stapled OCSP response\n"; return 1; } # verify status my $status = Net::SSLeay::OCSP_response_status($resp); if ($status != Net::SSLeay::OCSP_RESPONSE_STATUS_SUCCESSFUL()) { warn "OCSP response failure: $status\n"; return 1; } # verify signature - we have no OCSP_REQUEST here to check nonce if (!eval { Net::SSLeay::OCSP_response_verify($ssl,$resp) }) { warn "OCSP response verify failed\n"; return 1; } # check if the certificate is valid # we should check here against the peer_certificate my $cert = Net::SSLeay::get_peer_certificate(); my $certid = eval { Net::SSLeay::OCSP_cert2ids($ssl,$cert) } or do { warn "cannot get certid from cert: $@"; $cert_valid = -1; return 1; }; if ( $nextupd = eval { Net::SSLeay::OCSP_response_results($resp,$certid) }) { warn "certificate not revoked\n"; $cert_valid = 1; } else { warn "certificate not valid: $@"; $cert_valid = 0; } }); # do SSL handshake here .... # check if certificate revocation was checked already if ( ! defined $cert_valid) { # check revocation outside of SSL handshake by asking OCSP responder ... } elsif ( ! $cert_valid ) { die "certificate not valid - closing SSL connection"; } elsif ( $cert_valid<0 ) { die "cannot verify certificate revocation - self-signed ?"; } else { # everything fine ... } =head2 Using Net::SSLeay in multi-threaded applications B Net::SSLeay module implements all necessary stuff to be ready for multi-threaded environment - it requires openssl-0.9.7 or newer. The implementation fully follows thread safety related requirements of openssl library(see L). If you are about to use Net::SSLeay (or any other module based on Net::SSLeay) in multi-threaded perl application it is recommended to follow this best-practice: =head3 Initialization Load and initialize Net::SSLeay module in the main thread: use threads; use Net::SSLeay; Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); sub do_master_job { #... call whatever from Net::SSLeay } sub do_worker_job { #... call whatever from Net::SSLeay } #start threads my $master = threads->new(\&do_master_job, 'param1', 'param2'); my @workers = threads->new(\&do_worker_job, 'arg1', 'arg2') for (1..10); #waiting for all threads to finish $_->join() for (threads->list); NOTE: Openssl's C function (which is also aliased as C, C and C) is not re-entrant and multiple calls can cause a crash in threaded application. Net::SSLeay implements flags preventing repeated calls to this function, therefore even multiple initialization via Net::SSLeay::SSLeay_add_ssl_algorithms() should work without trouble. =head3 Using callbacks Do not use callbacks across threads (the module blocks cross-thread callback operations and throws a warning). Always do the callback setup, callback use and callback destruction within the same thread. =head3 Using openssl elements All openssl elements (X509, SSL_CTX, ...) can be directly passed between threads. use threads; use Net::SSLeay; Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); sub do_job { my $context = shift; Net::SSLeay::CTX_set_default_passwd_cb($context, sub { "secret" }); #... } my $c = Net::SSLeay::CTX_new(); threads->create(\&do_job, $c); Or: use threads; use Net::SSLeay; my $context; #does not need to be 'shared' Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); sub do_job { Net::SSLeay::CTX_set_default_passwd_cb($context, sub { "secret" }); #... } $context = Net::SSLeay::CTX_new(); threads->create(\&do_job); =head3 Using other perl modules based on Net::SSLeay It should be fine to use any other module based on L (like L) in multi-threaded applications. It is generally recommended to do any global initialization of such a module in the main thread before calling C<< threads->new(..) >> or C<< threads->create(..) >> but it might differ module by module. To be safe you can load and init Net::SSLeay explicitly in the main thread: use Net::SSLeay; use Other::SSLeay::Based::Module; Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); Or even safer: use Net::SSLeay; use Other::SSLeay::Based::Module; BEGIN { Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); } =head3 Combining Net::SSLeay with other modules linked with openssl B There are many other (XS) modules linked directly to openssl library (like L). As it is expected that also "another" module will call C at some point we have again a trouble with multiple openssl initialization by Net::SSLeay and "another" module. As you can expect Net::SSLeay is not able to avoid multiple initialization of openssl library called by "another" module, thus you have to handle this on your own (in some cases it might not be possible at all to avoid this). =head3 Threading with get_https and friends The convenience functions get_https, post_https etc all initialize the SSL library by calling Net::SSLeay::initialize which does the conventional library initialization: Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); Net::SSLeay::initialize initializes the SSL library at most once. You can override the Net::SSLeay::initialize function if you desire some other type of initialization behaviour by get_https and friends. You can call Net::SSLeay::initialize from your own code if you desire this conventional library initialization. =head2 Convenience routines To be used with Low level API Net::SSLeay::randomize($rn_seed_file,$additional_seed); Net::SSLeay::set_cert_and_key($ctx, $cert_path, $key_path); $cert = Net::SSLeay::dump_peer_certificate($ssl); Net::SSLeay::ssl_write_all($ssl, $message) or die "ssl write failure"; $got = Net::SSLeay::ssl_read_all($ssl) or die "ssl read failure"; $got = Net::SSLeay::ssl_read_CRLF($ssl [, $max_length]); $got = Net::SSLeay::ssl_read_until($ssl [, $delimit [, $max_length]]); Net::SSLeay::ssl_write_CRLF($ssl, $message); =over =item * randomize seeds the openssl PRNG with C (see the top of C for how to change or configure this) and optionally with user provided data. It is very important to properly seed your random numbers, so do not forget to call this. The high level API functions automatically call C so it is not needed with them. See also caveats. =item * set_cert_and_key takes two file names as arguments and sets the certificate and private key to those. This can be used to set either server certificates or client certificates. =item * dump_peer_certificate allows you to get a plaintext description of the certificate the peer (usually the server) presented to us. =item * ssl_read_all see ssl_write_all (below) =item * ssl_write_all C and C provide true blocking semantics for these operations (see limitation, below, for explanation). These are much preferred to the low level API equivalents (which implement BSD blocking semantics). The message argument to C can be a reference. This is helpful to avoid unnecessary copying when writing something big, e.g: $data = 'A' x 1000000000; Net::SSLeay::ssl_write_all($ssl, \$data) or die "ssl write failed"; =item * ssl_read_CRLF uses C to read in a line terminated with a carriage return followed by a linefeed (CRLF). The CRLF is included in the returned scalar. =item * ssl_read_until uses C to read from the SSL input stream until it encounters a programmer specified delimiter. If the delimiter is undefined, C<$/> is used. If C<$/> is undefined, C<\n> is used. One can optionally set a maximum length of bytes to read from the SSL input stream. =item * ssl_write_CRLF writes C<$message> and appends CRLF to the SSL output stream. =back =head2 Initialization In order to use the low level API you should start your programs with the following incantation: use Net::SSLeay qw(die_now die_if_ssl_error); Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); # Important! Net::SSLeay::ENGINE_load_builtin_engines(); # If you want built-in engines Net::SSLeay::ENGINE_register_all_complete(); # If you want built-in engines Net::SSLeay::randomize(); =head2 Error handling functions I can not emphasize the need to check for error enough. Use these functions even in the most simple programs, they will reduce debugging time greatly. Do not ask questions on the mailing list without having first sprinkled these in your code. =over =item * die_now =item * die_if_ssl_error C and C are used to conveniently print the SSLeay error stack when something goes wrong: Net::SSLeay::connect($ssl) or die_now("Failed SSL connect ($!)"); Net::SSLeay::write($ssl, "foo") or die_if_ssl_error("SSL write ($!)"); =item * print_errs You can also use C to dump the error stack without exiting the program. As can be seen, your code becomes much more readable if you import the error reporting functions into your main name space. =back =head2 Sockets Perl uses file handles for all I/O. While SSLeay has a quite flexible BIO mechanism and perl has an evolved PerlIO mechanism, this module still sticks to using file descriptors. Thus to attach SSLeay to a socket you should use C to extract the underlying file descriptor: Net::SSLeay::set_fd($ssl, fileno(S)); # Must use fileno You should also set C<$|> to 1 to eliminate STDIO buffering so you do not get confused if you use perl I/O functions to manipulate your socket handle. If you need to C on the socket, go right ahead, but be warned that OpenSSL does some internal buffering so SSL_read does not always return data even if the socket selected for reading (just keep on selecting and trying to read). C is no different from the C language OpenSSL in this respect. =head2 Callbacks You can establish a per-context verify callback function something like this: sub verify { my ($ok, $x509_store_ctx) = @_; print "Verifying certificate...\n"; ... return $ok; } It is used like this: Net::SSLeay::set_verify ($ssl, Net::SSLeay::VERIFY_PEER, \&verify); Per-context callbacks for decrypting private keys are implemented. Net::SSLeay::CTX_set_default_passwd_cb($ctx, sub { "top-secret" }); Net::SSLeay::CTX_use_PrivateKey_file($ctx, "key.pem", Net::SSLeay::FILETYPE_PEM) or die "Error reading private key"; Net::SSLeay::CTX_set_default_passwd_cb($ctx, undef); If Hello Extensions are supported by your OpenSSL, a session secret callback can be set up to be called when a session secret is set by openssl. Establish it like this: Net::SSLeay::set_session_secret_cb($ssl, \&session_secret_cb, $somedata); It will be called like this: sub session_secret_cb { my ($secret, \@cipherlist, \$preferredcipher, $somedata) = @_; } No other callbacks are implemented. You do not need to use any callback for simple (i.e. normal) cases where the SSLeay built-in verify mechanism satisfies your needs. It is required to reset these callbacks to undef immediately after use to prevent memory leaks, thread safety problems and crashes on exit that can occur if different threads set different callbacks. If you want to use callback stuff, see examples/callback.pl! It's the only one I am able to make work reliably. =head2 Low level API In addition to the high level functions outlined above, this module contains straight-forward access to CRYPTO and SSL parts of OpenSSL C API. See the C<*.h> headers from OpenSSL C distribution for a list of low level SSLeay functions to call (check SSLeay.xs to see if some function has been implemented). The module strips the initial C<"SSL_"> off of the SSLeay names. Generally you should use C in its place. Note that some functions are prefixed with C<"P_"> - these are very close to the original API however contain some kind of a wrapper making its interface more perl friendly. For example: In C: #include err = SSL_set_verify (ssl, SSL_VERIFY_CLIENT_ONCE, &your_call_back_here); In Perl: use Net::SSLeay; $err = Net::SSLeay::set_verify ($ssl, Net::SSLeay::VERIFY_CLIENT_ONCE, \&your_call_back_here); If the function does not start with C you should use the full function name, e.g.: $err = Net::SSLeay::ERR_get_error; The following new functions behave in perlish way: $got = Net::SSLeay::read($ssl); # Performs SSL_read, but returns $got # resized according to data received. # Returns undef on failure. Net::SSLeay::write($ssl, $foo) || die; # Performs SSL_write, but automatically # figures out the size of $foo =head3 Low level API: Version related functions =over =item * SSLeay B not available in Net-SSLeay-1.42 and before Gives version number (numeric) of underlaying openssl library. my $ver_number = Net::SSLeay::SSLeay(); # returns: the number identifying the openssl release # # 0x00903100 => openssl-0.9.3 # 0x00904100 => openssl-0.9.4 # 0x00905100 => openssl-0.9.5 # 0x0090600f => openssl-0.9.6 # 0x0090601f => openssl-0.9.6a # 0x0090602f => openssl-0.9.6b # ... # 0x009060df => openssl-0.9.6m # 0x0090700f => openssl-0.9.7 # 0x0090701f => openssl-0.9.7a # 0x0090702f => openssl-0.9.7b # ... # 0x009070df => openssl-0.9.7m # 0x0090800f => openssl-0.9.8 # 0x0090801f => openssl-0.9.8a # 0x0090802f => openssl-0.9.8b # ... # 0x0090814f => openssl-0.9.8t # 0x1000000f => openssl-1.0.0 # 0x1000004f => openssl-1.0.0d # 0x1000007f => openssl-1.0.0g You can use it like this: if (Net::SSLeay::SSLeay() < 0x0090800f) { die "you need openssl-0.9.8 or higher"; } =item * SSLeay_version B not available in Net-SSLeay-1.42 and before Gives version number (string) of underlaying openssl library. my $ver_string = Net::SSLeay::SSLeay_version($type); # $type # SSLEAY_VERSION - e.g. 'OpenSSL 1.0.0d 8 Feb 2011' # SSLEAY_CFLAGS - e.g. 'compiler: gcc -D_WINDLL -DOPENSSL_USE_APPLINK .....' # SSLEAY_BUILT_ON - e.g. 'built on: Fri May 6 00:00:46 GMT 2011' # SSLEAY_PLATFORM - e.g. 'platform: mingw' # SSLEAY_DIR - e.g. 'OPENSSLDIR: "z:/...."' # # returns: string Net::SSLeay::SSLeay_version(); #is equivalent to Net::SSLeay::SSLeay_version(SSLEAY_VERSION); Check openssl doc L =item * OpenSSL_version_num B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0 Gives version number (numeric) of underlaying openssl library. See L for interpreting the result. my $ver_number = Net::SSLeay::OpenSSL_version_num(); # returns: the number identifying the openssl release =item * OpenSSL_version B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0 Gives version number (string) of underlaying openssl library. my $ver_string = Net::SSLeay::OpenSSL_version($t); # $t # OPENSSL_VERSION - e.g. 'OpenSSL 1.1.0g 2 Nov 2017' # OPENSSL_CFLAGS - e.g. 'compiler: cc -DDSO_DLFCN -DHAVE_DLFCN_H .....' # OPENSSL_BUILT_ON - e.g. 'built on: reproducible build, date unspecified' # OPENSSL_PLATFORM - e.g. 'platform: darwin64-x86_64-cc' # OPENSSL_DIR - e.g. 'OPENSSLDIR: "/opt/openssl-1.1.0g"' # OPENSSL_ENGINES_DIR - e.g. 'ENGINESDIR: "/opt/openssl-1.1.0g/lib/engines-1.1"' # # returns: string Net::SSLeay::OpenSSL_version(); #is equivalent to Net::SSLeay::OpenSSL_version(OPENSSL_VERSION); Check openssl doc L =back =head3 Low level API: Initialization related functions =over =item * library_init Initialize SSL library by registering algorithms. my $rv = Net::SSLeay::library_init(); Check openssl doc L While the original function from OpenSSL always returns 1, Net::SSLeay adds a wrapper around it to make sure that the OpenSSL function is only called once. Thus the function will return 1 if initialization was done and 0 if not, i.e. if initialization was done already before. =item * add_ssl_algorithms The alias for L Net::SSLeay::add_ssl_algorithms(); =item * OpenSSL_add_ssl_algorithms The alias for L Net::SSLeay::OpenSSL_add_ssl_algorithms(); =item * SSLeay_add_ssl_algorithms The alias for L Net::SSLeay::SSLeay_add_ssl_algorithms(); =item * load_error_strings Registers the error strings for all libcrypto + libssl related functions. Net::SSLeay::load_error_strings(); # # returns: no return value Check openssl doc L =item * ERR_load_crypto_strings Registers the error strings for all libcrypto functions. No need to call this function if you have already called L. Net::SSLeay::ERR_load_crypto_strings(); # # returns: no return value Check openssl doc L =item * ERR_load_RAND_strings Registers the error strings for RAND related functions. No need to call this function if you have already called L. Net::SSLeay::ERR_load_RAND_strings(); # # returns: no return value =item * ERR_load_SSL_strings Registers the error strings for SSL related functions. No need to call this function if you have already called L. Net::SSLeay::ERR_load_SSL_strings(); # # returns: no return value =item * OpenSSL_add_all_algorithms B not available in Net-SSLeay-1.45 and before Add algorithms to internal table. Net::SSLeay::OpenSSL_add_all_algorithms(); # # returns: no return value Check openssl doc L =item * OPENSSL_add_all_algorithms_conf B not available in Net-SSLeay-1.45 and before Similar to L - will ALWAYS load the config file Net::SSLeay::OPENSSL_add_all_algorithms_conf(); # # returns: no return value =item * OPENSSL_add_all_algorithms_noconf B not available in Net-SSLeay-1.45 and before Similar to L - will NEVER load the config file Net::SSLeay::OPENSSL_add_all_algorithms_noconf(); # # returns: no return value =back =head3 Low level API: ERR_* and SSL_alert_* related functions B Please note that SSL_alert_* function have "SSL_" part stripped from their names. =over =item * ERR_clear_error Clear the error queue. Net::SSLeay::ERR_clear_error(); # # returns: no return value Check openssl doc L =item * ERR_error_string Generates a human-readable string representing the error code $error. my $rv = Net::SSLeay::ERR_error_string($error); # $error - (unsigned integer) error code # # returns: string Check openssl doc L =item * ERR_get_error Returns the earliest error code from the thread's error queue and removes the entry. This function can be called repeatedly until there are no more error codes to return. my $rv = Net::SSLeay::ERR_get_error(); # # returns: (unsigned integer) error code Check openssl doc L =item * ERR_peek_error Returns the earliest error code from the thread's error queue without modifying it. my $rv = Net::SSLeay::ERR_peek_error(); # # returns: (unsigned integer) error code Check openssl doc L =item * ERR_put_error Adds an error code to the thread's error queue. It signals that the error of $reason code reason occurred in function $func of library $lib, in line number $line of $file. Net::SSLeay::ERR_put_error($lib, $func, $reason, $file, $line); # $lib - (integer) library id (check openssl/err.h for constants e.g. ERR_LIB_SSL) # $func - (integer) function id (check openssl/ssl.h for constants e.g. SSL_F_SSL23_READ) # $reason - (integer) reason id (check openssl/ssl.h for constants e.g. SSL_R_SSL_HANDSHAKE_FAILURE) # $file - (string) file name # $line - (integer) line number in $file # # returns: no return value Check openssl doc L and L =item * alert_desc_string Returns a two letter string as a short form describing the reason of the alert specified by value. my $rv = Net::SSLeay::alert_desc_string($value); # $value - (integer) allert id (check openssl/ssl.h for SSL3_AD_* and TLS1_AD_* constants) # # returns: description string (2 letters) Check openssl doc L =item * alert_desc_string_long Returns a string describing the reason of the alert specified by value. my $rv = Net::SSLeay::alert_desc_string_long($value); # $value - (integer) allert id (check openssl/ssl.h for SSL3_AD_* and TLS1_AD_* constants) # # returns: description string Check openssl doc L =item * alert_type_string Returns a one letter string indicating the type of the alert specified by value. my $rv = Net::SSLeay::alert_type_string($value); # $value - (integer) allert id (check openssl/ssl.h for SSL3_AD_* and TLS1_AD_* constants) # # returns: string (1 letter) Check openssl doc L =item * alert_type_string_long Returns a string indicating the type of the alert specified by value. my $rv = Net::SSLeay::alert_type_string_long($value); # $value - (integer) allert id (check openssl/ssl.h for SSL3_AD_* and TLS1_AD_* constants) # # returns: string Check openssl doc L =back =head3 Low level API: SSL_METHOD_* related functions =over =item * SSLv23_method, SSLv23_server_method and SSLv23_client_method B not available in Net-SSLeay-1.82 and before. Returns SSL_METHOD structure corresponding to general-purpose version-flexible TLS method, the return value can be later used as a param of L. B Consider using TLS_method, TLS_server_method or TLS_client_method with new code. my $rv = Net::SSLeay::SSLv2_method(); # # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) =item * SSLv2_method Returns SSL_METHOD structure corresponding to SSLv2 method, the return value can be later used as a param of L. Only available where supported by the underlying openssl. my $rv = Net::SSLeay::SSLv2_method(); # # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) =item * SSLv3_method Returns SSL_METHOD structure corresponding to SSLv3 method, the return value can be later used as a param of L. my $rv = Net::SSLeay::SSLv3_method(); # # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) Check openssl doc L =item * TLSv1_method, TLSv1_server_method and TLSv1_client_method B Server and client methods not available in Net-SSLeay-1.82 and before. Returns SSL_METHOD structure corresponding to TLSv1 method, the return value can be later used as a param of L. my $rv = Net::SSLeay::TLSv1_method(); # # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) Check openssl doc L =item * TLSv1_1_method, TLSv1_1_server_method and TLSv1_1_client_method B Server and client methods not available in Net-SSLeay-1.82 and before. Returns SSL_METHOD structure corresponding to TLSv1_1 method, the return value can be later used as a param of L. Only available where supported by the underlying openssl. my $rv = Net::SSLeay::TLSv1_1_method(); # # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) Check openssl doc L =item * TLSv1_2_method, TLSv1_2_server_method and TLSv1_2_client_method B Server and client methods not available in Net-SSLeay-1.82 and before. Returns SSL_METHOD structure corresponding to TLSv1_2 method, the return value can be later used as a param of L. Only available where supported by the underlying openssl. my $rv = Net::SSLeay::TLSv1_2_method(); # # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) Check openssl doc L =item * TLS_method, TLS_server_method and TLS_client_method B Not available in Net-SSLeay-1.82 and before. Returns SSL_METHOD structure corresponding to general-purpose version-flexible TLS method, the return value can be later used as a param of L. Only available where supported by the underlying openssl. my $rv = Net::SSLeay::TLS_method(); # # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) Check openssl doc L =back =head3 Low level API: ENGINE_* related functions =over =item * ENGINE_load_builtin_engines B Requires an OpenSSL build with dynamic engine loading support. Load all bundled ENGINEs into memory and make them visible. Net::SSLeay::ENGINE_load_builtin_engines(); # # returns: no return value Check openssl doc L =item * ENGINE_register_all_complete B Requires an OpenSSL build with dynamic engine loading support. Register all loaded ENGINEs for every algorithm they collectively implement. Net::SSLeay::ENGINE_register_all_complete(); # # returns: no return value Check openssl doc L =item * ENGINE_set_default B Requires an OpenSSL build with dynamic engine loading support. Set default engine to $e + set its flags to $flags. my $rv = Net::SSLeay::ENGINE_set_default($e, $flags); # $e - value corresponding to openssl's ENGINE structure # $flags - (integer) engine flags # flags value can be made by bitwise "OR"ing: # 0x0001 - ENGINE_METHOD_RSA # 0x0002 - ENGINE_METHOD_DSA # 0x0004 - ENGINE_METHOD_DH # 0x0008 - ENGINE_METHOD_RAND # 0x0010 - ENGINE_METHOD_ECDH # 0x0020 - ENGINE_METHOD_ECDSA # 0x0040 - ENGINE_METHOD_CIPHERS # 0x0080 - ENGINE_METHOD_DIGESTS # 0x0100 - ENGINE_METHOD_STORE # 0x0200 - ENGINE_METHOD_PKEY_METHS # 0x0400 - ENGINE_METHOD_PKEY_ASN1_METHS # Obvious all-or-nothing cases: # 0xFFFF - ENGINE_METHOD_ALL # 0x0000 - ENGINE_METHOD_NONE # # returns: 1 on success, 0 on failure Check openssl doc L =item * ENGINE_by_id Get ENGINE by its identification $id. B Requires an OpenSSL build with dynamic engine loading support. my $rv = Net::SSLeay::ENGINE_by_id($id); # $id - (string) engine identification e.g. "dynamic" # # returns: value corresponding to openssl's ENGINE structure (0 on failure) Check openssl doc L =back =head3 Low level API: EVP_PKEY_* related functions =over =item * EVP_PKEY_copy_parameters Copies the parameters from key $from to key $to. my $rv = Net::SSLeay::EVP_PKEY_copy_parameters($to, $from); # $to - value corresponding to openssl's EVP_PKEY structure # $from - value corresponding to openssl's EVP_PKEY structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * EVP_PKEY_new B not available in Net-SSLeay-1.45 and before Creates a new EVP_PKEY structure. my $rv = Net::SSLeay::EVP_PKEY_new(); # # returns: value corresponding to openssl's EVP_PKEY structure (0 on failure) Check openssl doc L =item * EVP_PKEY_free B not available in Net-SSLeay-1.45 and before Free an allocated EVP_PKEY structure. Net::SSLeay::EVP_PKEY_free($pkey); # $pkey - value corresponding to openssl's EVP_PKEY structure # # returns: no return value Check openssl doc L =item * EVP_PKEY_assign_RSA B not available in Net-SSLeay-1.45 and before Set the key referenced by $pkey to $key B No reference counter will be increased, i.e. $key will be freed if $pkey is freed. my $rv = Net::SSLeay::EVP_PKEY_assign_RSA($pkey, $key); # $pkey - value corresponding to openssl's EVP_PKEY structure # $key - value corresponding to openssl's RSA structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * EVP_PKEY_assign_EC_KEY B not available in Net-SSLeay-1.74 and before Set the key referenced by $pkey to $key B No reference counter will be increased, i.e. $key will be freed if $pkey is freed. my $rv = Net::SSLeay::EVP_PKEY_assign_EC_KEY($pkey, $key); # $pkey - value corresponding to openssl's EVP_PKEY structure # $key - value corresponding to openssl's EC_KEY structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * EVP_PKEY_bits B not available in Net-SSLeay-1.45 and before Returns the size of the key $pkey in bits. my $rv = Net::SSLeay::EVP_PKEY_bits($pkey); # $pkey - value corresponding to openssl's EVP_PKEY structure # # returns: size in bits =item * EVP_PKEY_size B not available in Net-SSLeay-1.45 and before Returns the maximum size of a signature in bytes. The actual signature may be smaller. my $rv = Net::SSLeay::EVP_PKEY_size($pkey); # $pkey - value corresponding to openssl's EVP_PKEY structure # # returns: the maximum size in bytes Check openssl doc L =item * EVP_PKEY_id B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.0 Returns $pkey type (integer value of corresponding NID). my $rv = Net::SSLeay::EVP_PKEY_id($pkey); # $pkey - value corresponding to openssl's EVP_PKEY structure # # returns: (integer) key type Example: my $pubkey = Net::SSLeay::X509_get_pubkey($x509); my $type = Net::SSLeay::EVP_PKEY_id($pubkey); print Net::SSLeay::OBJ_nid2sn($type); #prints e.g. 'rsaEncryption' =back =head3 Low level API: PEM_* related functions Check openssl doc L =over =item * PEM_read_bio_X509 B not available in Net-SSLeay-1.45 and before Loads PEM formatted X509 certificate via given BIO structure. my $rv = Net::SSLeay::PEM_read_bio_X509($bio); # $bio - value corresponding to openssl's BIO structure # # returns: value corresponding to openssl's X509 structure (0 on failure) Example: my $bio = Net::SSLeay::BIO_new_file($filename, 'r'); my $x509 = Net::SSLeay::PEM_read_bio_X509($bio); Net::SSLeay::BIO_free($bio); =item * PEM_read_bio_X509_REQ B not available in Net-SSLeay-1.45 and before Loads PEM formatted X509_REQ object via given BIO structure. my $rv = Net::SSLeay::PEM_read_bio_X509_REQ($bio, $x=NULL, $cb=NULL, $u=NULL); # $bio - value corresponding to openssl's BIO structure # # returns: value corresponding to openssl's X509_REQ structure (0 on failure) Example: my $bio = Net::SSLeay::BIO_new_file($filename, 'r'); my $x509_req = Net::SSLeay::PEM_read_bio_X509_REQ($bio); Net::SSLeay::BIO_free($bio); =item * PEM_read_bio_DHparams Reads DH structure from BIO. my $rv = Net::SSLeay::PEM_read_bio_DHparams($bio); # $bio - value corresponding to openssl's BIO structure # # returns: value corresponding to openssl's DH structure (0 on failure) =item * PEM_read_bio_X509_CRL Reads X509_CRL structure from BIO. my $rv = Net::SSLeay::PEM_read_bio_X509_CRL($bio); # $bio - value corresponding to openssl's BIO structure # # returns: value corresponding to openssl's X509_CRL structure (0 on failure) =item * PEM_read_bio_PrivateKey B not available in Net-SSLeay-1.45 and before Loads PEM formatted private key via given BIO structure. my $rv = Net::SSLeay::PEM_read_bio_PrivateKey($bio, $cb, $data); # $bio - value corresponding to openssl's BIO structure # $cb - reference to perl callback function # $data - data that will be passed to callback function (see examples below) # # returns: value corresponding to openssl's EVP_PKEY structure (0 on failure) Example: my $bio = Net::SSLeay::BIO_new_file($filename, 'r'); my $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio); #ask for password if needed Net::SSLeay::BIO_free($bio); To use password you have the following options: $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio, \&callback_func); # use callback func for getting password $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio, \&callback_func, $data); # use callback_func + pass $data to callback_func $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio, undef, "secret"); # use password "secret" $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio, undef, ""); # use empty password Callback function signature: sub callback_func { my ($max_passwd_size, $rwflag, $data) = @_; # $max_passwd_size - maximum size of returned password (longer values will be discarded) # $rwflag - indicates whether we are loading (0) or storing (1) - for PEM_read_bio_PrivateKey always 0 # $data - the data passed to PEM_read_bio_PrivateKey as 3rd parameter return "secret"; } =item * PEM_X509_INFO_read_bio Reads a BIO containing a PEM formatted file into a STACK_OF(X509_INFO) structure. my $rv = Net::SSLeay::PEM_X509_INFO_read_bio($bio); # $bio - value corresponding to openssl's BIO structure # # returns: value corresponding to openssl's STACK_OF(X509_INFO) structure. Example: my $bio = Net::SSLeay::BIO_new_file($filename, 'r'); my $sk_x509_info = Net::SSLeay::PEM_X509_INFO_read_bio($bio); Net::SSLeay::BIO_free($bio); =item * PEM_get_string_X509 B Does not exactly correspond to any low level API function Converts/exports X509 certificate to string (PEM format). Net::SSLeay::PEM_get_string_X509($x509); # $x509 - value corresponding to openssl's X509 structure # # returns: string with $x509 in PEM format =item * PEM_get_string_PrivateKey B not available in Net-SSLeay-1.45 and before Converts public key $pk into PEM formatted string (optionally protected with password). my $rv = Net::SSLeay::PEM_get_string_PrivateKey($pk, $passwd, $enc_alg); # $pk - value corresponding to openssl's EVP_PKEY structure # $passwd - [optional] (string) password to use for key encryption # $enc_alg - [optional] algorithm to use for key encryption (default: DES_CBC) - value corresponding to openssl's EVP_CIPHER structure # # returns: PEM formatted string Examples: $pem_privkey = Net::SSLeay::PEM_get_string_PrivateKey($pk); $pem_privkey = Net::SSLeay::PEM_get_string_PrivateKey($pk, "secret"); $pem_privkey = Net::SSLeay::PEM_get_string_PrivateKey($pk, "secret", Net::SSLeay::EVP_get_cipherbyname("DES-EDE3-CBC")); =item * PEM_get_string_X509_CRL B not available in Net-SSLeay-1.45 and before Converts X509_CRL object $x509_crl into PEM formatted string. Net::SSLeay::PEM_get_string_X509_CRL($x509_crl); # $x509_crl - value corresponding to openssl's X509_CRL structure # # returns: no return value =item * PEM_get_string_X509_REQ B not available in Net-SSLeay-1.45 and before Converts X509_REQ object $x509_crl into PEM formatted string. Net::SSLeay::PEM_get_string_X509_REQ($x509_req); # $x509_req - value corresponding to openssl's X509_REQ structure # # returns: no return value =back =head3 Low level API: d2i_* (DER format) related functions =over =item * d2i_X509_bio B not available in Net-SSLeay-1.45 and before Loads DER formatted X509 certificate via given BIO structure. my $rv = Net::SSLeay::d2i_X509_bio($bp); # $bp - value corresponding to openssl's BIO structure # # returns: value corresponding to openssl's X509 structure (0 on failure) Example: my $bio = Net::SSLeay::BIO_new_file($filename, 'rb'); my $x509 = Net::SSLeay::d2i_X509_bio($bio); Net::SSLeay::BIO_free($bio); Check openssl doc L =item * d2i_X509_CRL_bio B not available in Net-SSLeay-1.45 and before Loads DER formatted X509_CRL object via given BIO structure. my $rv = Net::SSLeay::d2i_X509_CRL_bio($bp); # $bp - value corresponding to openssl's BIO structure # # returns: value corresponding to openssl's X509_CRL structure (0 on failure) Example: my $bio = Net::SSLeay::BIO_new_file($filename, 'rb'); my $x509_crl = Net::SSLeay::d2i_X509_CRL_bio($bio); Net::SSLeay::BIO_free($bio); =item * d2i_X509_REQ_bio B not available in Net-SSLeay-1.45 and before Loads DER formatted X509_REQ object via given BIO structure. my $rv = Net::SSLeay::d2i_X509_REQ_bio($bp); # $bp - value corresponding to openssl's BIO structure # # returns: value corresponding to openssl's X509_REQ structure (0 on failure) Example: my $bio = Net::SSLeay::BIO_new_file($filename, 'rb'); my $x509_req = Net::SSLeay::d2i_X509_REQ_bio($bio); Net::SSLeay::BIO_free($bio); =back =head3 Low level API: PKCS12 related functions =over =item * P_PKCS12_load_file B not available in Net-SSLeay-1.45 and before Loads X509 certificate + private key + certificates of CA chain (if present in PKCS12 file). my ($privkey, $cert, @cachain) = Net::SSLeay::P_PKCS12_load_file($filename, $load_chain, $password); # $filename - name of PKCS12 file # $load_chain - [optional] whether load (1) or not(0) CA chain (default: 0) # $password - [optional] password for private key # # returns: triplet ($privkey, $cert, @cachain) # $privkey - value corresponding to openssl's EVP_PKEY structure # $cert - value corresponding to openssl's X509 structure # @cachain - array of values corresponding to openssl's X509 structure (empty if no CA chain in PKCS12) B after you do the job you need to call X509_free() on $privkey + all members of @cachain and EVP_PKEY_free() on $privkey. Examples: my ($privkey, $cert) = Net::SSLeay::P_PKCS12_load_file($filename); #or my ($privkey, $cert) = Net::SSLeay::P_PKCS12_load_file($filename, 0, $password); #or my ($privkey, $cert, @cachain) = Net::SSLeay::P_PKCS12_load_file($filename, 1); #or my ($privkey, $cert, @cachain) = Net::SSLeay::P_PKCS12_load_file($filename, 1, $password); #BEWARE: THIS IS WRONG - MEMORY LEAKS! (you cannot free @cachain items) my ($privkey, $cert) = Net::SSLeay::P_PKCS12_load_file($filename, 1, $password); B With some combinations of Windows, perl, compiler and compiler options, you may see a runtime error "no OPENSSL_Applink", when calling Net::SSLeay::P_PKCS12_load_file. See README.Win32 for more details. =back =head3 Low level API: SESSION_* related functions =over =item * d2i_SSL_SESSION B does not work in Net-SSLeay-1.85 and before Transforms the binary ASN1 representation string of an SSL/TLS session into an SSL_SESSION object. my $ses = Net::SSLeay::d2i_SSL_SESSION($data); # $data - the session as ASN1 representation string # # returns: $ses - the new SSL_SESSION Check openssl doc L =item * i2d_SSL_SESSION B does not work in Net-SSLeay-1.85 and before Transforms the SSL_SESSION object in into the ASN1 representation and returns it as string. my $data = Net::SSLeay::i2d_SSL_SESSION($ses); # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: $data - session as string Check openssl doc L =item * SESSION_new Creates a new SSL_SESSION structure. my $rv = Net::SSLeay::SESSION_new(); # # returns: value corresponding to openssl's SSL_SESSION structure (0 on failure) =item * SESSION_free Free an allocated SSL_SESSION structure. Net::SSLeay::SESSION_free($ses); # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: no return value Check openssl doc L =item * SESSION_up_ref B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0 or LibreSSL 2.7.0 Increases the reference counter on a SSL_SESSION structure. Net::SSLeay::SESSION_up_ref($ses); # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: 1 on success else 0 Check openssl doc L =item * SESSION_dup B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Duplicates a SSL_SESSION structure. Net::SSLeay::SESSION_dup($ses); # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: the duplicated session Check openssl doc L =item * SESSION_is_resumable B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Determine whether an SSL_SESSION object can be used for resumption. Net::SSLeay::SESSION_is_resumable($ses); # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: (integer) 1 if it can or 0 if not Check openssl doc L =item * SESSION_cmp Compare two SSL_SESSION structures. my $rv = Net::SSLeay::SESSION_cmp($sesa, $sesb); # $sesa - value corresponding to openssl's SSL_SESSION structure # $sesb - value corresponding to openssl's SSL_SESSION structure # # returns: 0 if the two structures are the same B Not available in openssl 1.0 or later =item * SESSION_get_app_data Can be used to get application defined value/data. my $rv = Net::SSLeay::SESSION_get_app_data($ses); # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: string/buffer/pointer ??? =item * SESSION_set_app_data Can be used to set some application defined value/data. my $rv = Net::SSLeay::SESSION_set_app_data($s, $a); # $s - value corresponding to openssl's SSL_SESSION structure # $a - (string/buffer/pointer ???) data # # returns: ??? =item * SESSION_get_ex_data Is used to retrieve the information for $idx from session $ses. my $rv = Net::SSLeay::SESSION_get_ex_data($ses, $idx); # $ses - value corresponding to openssl's SSL_SESSION structure # $idx - (integer) index for application specific data # # returns: pointer to ??? Check openssl doc L =item * SESSION_set_ex_data Is used to store application data at arg for idx into the session object. my $rv = Net::SSLeay::SESSION_set_ex_data($ss, $idx, $data); # $ss - value corresponding to openssl's SSL_SESSION structure # $idx - (integer) ??? # $data - (pointer) ??? # # returns: 1 on success, 0 on failure Check openssl doc L =item * SESSION_get_ex_new_index Is used to register a new index for application specific data. my $rv = Net::SSLeay::SESSION_get_ex_new_index($argl, $argp, $new_func, $dup_func, $free_func); # $argl - (long) ??? # $argp - (pointer) ??? # $new_func - function pointer ??? (CRYPTO_EX_new *) # $dup_func - function pointer ??? (CRYPTO_EX_dup *) # $free_func - function pointer ??? (CRYPTO_EX_free *) # # returns: (integer) ??? Check openssl doc L =item * SESSION_get_master_key B Does not exactly correspond to any low level API function Returns 'master_key' value from SSL_SESSION structure $s Net::SSLeay::SESSION_get_master_key($s); # $s - value corresponding to openssl's SSL_SESSION structure # # returns: master key (binary data) =item * SESSION_set_master_key Sets 'master_key' value for SSL_SESSION structure $s Net::SSLeay::SESSION_set_master_key($s, $key); # $s - value corresponding to openssl's SSL_SESSION structure # $key - master key (binary data) # # returns: no return value Not available with OpenSSL 1.1 and later. Code that previously used SESSION_set_master_key must now set $secret in the session_secret callback set with SSL_set_session_secret_cb. =item * SESSION_get_time Returns the time at which the session s was established. The time is given in seconds since 1.1.1970. my $rv = Net::SSLeay::SESSION_get_time($s); # $s - value corresponding to openssl's SSL_SESSION structure # # returns: timestamp (seconds since 1.1.1970) Check openssl doc L =item * get_time Technically the same functionality as L. my $rv = Net::SSLeay::get_time($s); =item * SESSION_get_timeout Returns the timeout value set for session $s in seconds. my $rv = Net::SSLeay::SESSION_get_timeout($s); # $s - value corresponding to openssl's SSL_SESSION structure # # returns: timeout (in seconds) Check openssl doc L =item * get_timeout Technically the same functionality as L. my $rv = Net::SSLeay::get_timeout($s); =item * SESSION_print B Does not exactly correspond to any low level API function Prints session details (e.g. protocol version, cipher, session-id ...) to BIO. my $rv = Net::SSLeay::SESSION_print($fp, $ses); # $fp - value corresponding to openssl's BIO structure # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: 1 on success, 0 on failure You have to use necessary BIO functions like this: # let us have $ssl corresponding to openssl's SSL structure my $ses = Net::SSLeay::get_session($ssl); my $bio = Net::SSLeay::BIO_new(&Net::SSLeay::BIO_s_mem); Net::SSLeay::SESSION_print($bio, $ses); print Net::SSLeay::BIO_read($bio); =item * SESSION_print_fp Prints session details (e.g. protocol version, cipher, session-id ...) to file handle. my $rv = Net::SSLeay::SESSION_print_fp($fp, $ses); # $fp - perl file handle # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: 1 on success, 0 on failure Example: # let us have $ssl corresponding to openssl's SSL structure my $ses = Net::SSLeay::get_session($ssl); open my $fh, ">", "output.txt"; Net::SSLeay::SESSION_print_fp($fh,$ses); =item * SESSION_set_time Replaces the creation time of the session s with the chosen value $t (seconds since 1.1.1970). my $rv = Net::SSLeay::SESSION_set_time($ses, $t); # $ses - value corresponding to openssl's SSL_SESSION structure # $t - time value # # returns: 1 on success Check openssl doc L =item * set_time Technically the same functionality as L. my $rv = Net::SSLeay::set_time($ses, $t); =item * SESSION_set_timeout Sets the timeout value for session s in seconds to $t. my $rv = Net::SSLeay::SESSION_set_timeout($s, $t); # $s - value corresponding to openssl's SSL_SESSION structure # $t - timeout (in seconds) # # returns: 1 on success Check openssl doc L =item * set_timeout Technically the same functionality as L. my $rv = Net::SSLeay::set_timeout($ses, $t); =back =head3 Low level API: SSL_CTX_* related functions B Please note that the function described in this chapter have "SSL_" part stripped from their original openssl names. =over =item * CTX_add_client_CA Adds the CA name extracted from $cacert to the list of CAs sent to the client when requesting a client certificate for $ctx. my $rv = Net::SSLeay::CTX_add_client_CA($ctx, $cacert); # $ctx - value corresponding to openssl's SSL_CTX structure # $cacert - value corresponding to openssl's X509 structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * CTX_add_extra_chain_cert Adds the certificate $x509 to the certificate chain presented together with the certificate. Several certificates can be added one after the other. my $rv = Net::SSLeay::CTX_add_extra_chain_cert($ctx, $x509); # $ctx - value corresponding to openssl's SSL_CTX structure # $x509 - value corresponding to openssl's X509 structure # # returns: 1 on success, check out the error stack to find out the reason for failure otherwise Check openssl doc L =item * CTX_add_session Adds the session $ses to the context $ctx. my $rv = Net::SSLeay::CTX_add_session($ctx, $ses); # $ctx - value corresponding to openssl's SSL_CTX structure # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * CTX_callback_ctrl ??? (more info needed) my $rv = Net::SSLeay::CTX_callback_ctrl($ctx, $cmd, $fp); # $ctx - value corresponding to openssl's SSL_CTX structure # $cmd - (integer) command id # $fp - (function pointer) ??? # # returns: ??? Check openssl doc L =item * CTX_check_private_key Checks the consistency of a private key with the corresponding certificate loaded into $ctx. my $rv = Net::SSLeay::CTX_check_private_key($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * CTX_ctrl Internal handling function for SSL_CTX objects. B openssl doc says: This function should never be called directly! my $rv = Net::SSLeay::CTX_ctrl($ctx, $cmd, $larg, $parg); # $ctx - value corresponding to openssl's SSL_CTX structure # $cmd - (integer) command id # $larg - (integer) long ??? # $parg - (string/pointer) ??? # # returns: (long) result of given command ??? #valid $cmd values 1 - SSL_CTRL_NEED_TMP_RSA 2 - SSL_CTRL_SET_TMP_RSA 3 - SSL_CTRL_SET_TMP_DH 4 - SSL_CTRL_SET_TMP_ECDH 5 - SSL_CTRL_SET_TMP_RSA_CB 6 - SSL_CTRL_SET_TMP_DH_CB 7 - SSL_CTRL_SET_TMP_ECDH_CB 8 - SSL_CTRL_GET_SESSION_REUSED 9 - SSL_CTRL_GET_CLIENT_CERT_REQUEST 10 - SSL_CTRL_GET_NUM_RENEGOTIATIONS 11 - SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 12 - SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 13 - SSL_CTRL_GET_FLAGS 14 - SSL_CTRL_EXTRA_CHAIN_CERT 15 - SSL_CTRL_SET_MSG_CALLBACK 16 - SSL_CTRL_SET_MSG_CALLBACK_ARG 17 - SSL_CTRL_SET_MTU 20 - SSL_CTRL_SESS_NUMBER 21 - SSL_CTRL_SESS_CONNECT 22 - SSL_CTRL_SESS_CONNECT_GOOD 23 - SSL_CTRL_SESS_CONNECT_RENEGOTIATE 24 - SSL_CTRL_SESS_ACCEPT 25 - SSL_CTRL_SESS_ACCEPT_GOOD 26 - SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 27 - SSL_CTRL_SESS_HIT 28 - SSL_CTRL_SESS_CB_HIT 29 - SSL_CTRL_SESS_MISSES 30 - SSL_CTRL_SESS_TIMEOUTS 31 - SSL_CTRL_SESS_CACHE_FULL 32 - SSL_CTRL_OPTIONS 33 - SSL_CTRL_MODE 40 - SSL_CTRL_GET_READ_AHEAD 41 - SSL_CTRL_SET_READ_AHEAD 42 - SSL_CTRL_SET_SESS_CACHE_SIZE 43 - SSL_CTRL_GET_SESS_CACHE_SIZE 44 - SSL_CTRL_SET_SESS_CACHE_MODE 45 - SSL_CTRL_GET_SESS_CACHE_MODE 50 - SSL_CTRL_GET_MAX_CERT_LIST 51 - SSL_CTRL_SET_MAX_CERT_LIST 52 - SSL_CTRL_SET_MAX_SEND_FRAGMENT 53 - SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 54 - SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 55 - SSL_CTRL_SET_TLSEXT_HOSTNAME 56 - SSL_CTRL_SET_TLSEXT_DEBUG_CB 57 - SSL_CTRL_SET_TLSEXT_DEBUG_ARG 58 - SSL_CTRL_GET_TLSEXT_TICKET_KEYS 59 - SSL_CTRL_SET_TLSEXT_TICKET_KEYS 60 - SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT 61 - SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 62 - SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 63 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 64 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 65 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 66 - SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 67 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 68 - SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 69 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 70 - SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 71 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 72 - SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 73 - DTLS_CTRL_GET_TIMEOUT 74 - DTLS_CTRL_HANDLE_TIMEOUT 75 - DTLS_CTRL_LISTEN 76 - SSL_CTRL_GET_RI_SUPPORT 77 - SSL_CTRL_CLEAR_OPTIONS 78 - SSL_CTRL_CLEAR_MODE 82 - SSL_CTRL_GET_EXTRA_CHAIN_CERTS 83 - SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 88 - SSL_CTRL_CHAIN 89 - SSL_CTRL_CHAIN_CERT 90 - SSL_CTRL_GET_CURVES 91 - SSL_CTRL_SET_CURVES 92 - SSL_CTRL_SET_CURVES_LIST 93 - SSL_CTRL_GET_SHARED_CURVE 94 - SSL_CTRL_SET_ECDH_AUTO 97 - SSL_CTRL_SET_SIGALGS 98 - SSL_CTRL_SET_SIGALGS_LIST 99 - SSL_CTRL_CERT_FLAGS 100 - SSL_CTRL_CLEAR_CERT_FLAGS 101 - SSL_CTRL_SET_CLIENT_SIGALGS 102 - SSL_CTRL_SET_CLIENT_SIGALGS_LIST 103 - SSL_CTRL_GET_CLIENT_CERT_TYPES 104 - SSL_CTRL_SET_CLIENT_CERT_TYPES 105 - SSL_CTRL_BUILD_CERT_CHAIN 106 - SSL_CTRL_SET_VERIFY_CERT_STORE 107 - SSL_CTRL_SET_CHAIN_CERT_STORE 108 - SSL_CTRL_GET_PEER_SIGNATURE_NID 109 - SSL_CTRL_GET_SERVER_TMP_KEY 110 - SSL_CTRL_GET_RAW_CIPHERLIST 111 - SSL_CTRL_GET_EC_POINT_FORMATS 112 - SSL_CTRL_GET_TLSA_RECORD 113 - SSL_CTRL_SET_TLSA_RECORD 114 - SSL_CTRL_PULL_TLSA_RECORD Check openssl doc L =item * CTX_flush_sessions Causes a run through the session cache of $ctx to remove sessions expired at time $tm. Net::SSLeay::CTX_flush_sessions($ctx, $tm); # $ctx - value corresponding to openssl's SSL_CTX structure # $tm - specifies the time which should be used for the expiration test (seconds since 1.1.1970) # # returns: no return value Check openssl doc L =item * CTX_free Free an allocated SSL_CTX object. Net::SSLeay::CTX_free($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: no return value Check openssl doc L =item * CTX_get_app_data Can be used to get application defined value/data. my $rv = Net::SSLeay::CTX_get_app_data($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: string/buffer/pointer ??? =item * CTX_set_app_data Can be used to set some application defined value/data. my $rv = Net::SSLeay::CTX_set_app_data($ctx, $arg); # $ctx - value corresponding to openssl's SSL_CTX structure # $arg - (string/buffer/pointer ???) data # # returns: ??? =item * CTX_get0_param B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 Returns the current verification parameters. my $vpm = Net::SSLeay::CTX_get0_param($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: value corresponding to openssl's X509_VERIFY_PARAM structure Check openssl doc L =item * CTX_get_cert_store Returns the current certificate verification storage. my $rv = Net::SSLeay::CTX_get_cert_store($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: value corresponding to openssl's X509_STORE structure (0 on failure) Check openssl doc L =item * CTX_get_client_CA_list Returns the list of client CAs explicitly set for $ctx using L. my $rv = Net::SSLeay::CTX_get_client_CA_list($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: value corresponding to openssl's X509_NAME_STACK structure (0 on failure) Check openssl doc L =item * CTX_get_ex_data Is used to retrieve the information for index $idx from $ctx. my $rv = Net::SSLeay::CTX_get_ex_data($ssl, $idx); # $ssl - value corresponding to openssl's SSL_CTX structure # $idx - (integer) index for application specific data # # returns: pointer to ??? Check openssl doc L =item * CTX_get_ex_new_index Is used to register a new index for application specific data. my $rv = Net::SSLeay::CTX_get_ex_new_index($argl, $argp, $new_func, $dup_func, $free_func); # $argl - (long) ??? # $argp - (pointer) ??? # $new_func - function pointer ??? (CRYPTO_EX_new *) # $dup_func - function pointer ??? (CRYPTO_EX_dup *) # $free_func - function pointer ??? (CRYPTO_EX_free *) # # returns: (integer) ??? Check openssl doc L =item * CTX_get_mode Returns the mode set for ctx. my $rv = Net::SSLeay::CTX_get_mode($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: mode (bitmask) #to decode the return value (bitmask) use: 0x00000001 corresponds to SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000002 corresponds to SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000004 corresponds to SSL_MODE_AUTO_RETRY 0x00000008 corresponds to SSL_MODE_NO_AUTO_CHAIN 0x00000010 corresponds to SSL_MODE_RELEASE_BUFFERS (note: some of the bits might not be supported by older openssl versions) Check openssl doc L =item * CTX_set_mode Adds the mode set via bitmask in $mode to $ctx. Options already set before are not cleared. my $rv = Net::SSLeay::CTX_set_mode($ctx, $mode); # $ctx - value corresponding to openssl's SSL_CTX structure # $mode - mode bitmask # # returns: the new mode bitmask after adding $mode For bitmask details see L (above). Check openssl doc L =item * CTX_get_options Returns the options (bitmask) set for $ctx. my $rv = Net::SSLeay::CTX_get_options($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: options (bitmask) B The available constants and their values in bitmask depend on the TLS library. For example, SSL_OP_NO_TLSv1_3 became available much later than SSL_OP_NO_COMPRESS which is already deprecated by some libraries. Also, some previously used option values have been recycled and are now used for newer options. See the list of constants in this document for options Net::SSLeay currently supports. You are strongly encouraged to B if you need to use numeric values directly. The following is a sample of historic values. It may not be correct anymore. #to decode the return value (bitmask) use: 0x00000004 corresponds to SSL_OP_LEGACY_SERVER_CONNECT 0x00000800 corresponds to SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00004000 corresponds to SSL_OP_NO_TICKET 0x00010000 corresponds to SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00400000 corresponds to SSL_OP_CIPHER_SERVER_PREFERENCE 0x04000000 corresponds to SSL_OP_NO_TLSv1 Check openssl doc L =item * CTX_set_options Adds the options set via bitmask in $options to ctx. Options already set before are not cleared. Net::SSLeay::CTX_set_options($ctx, $options); # $ctx - value corresponding to openssl's SSL_CTX structure # $options - options bitmask # # returns: the new options bitmask after adding $options For bitmask details see L (above). Check openssl doc L =item * CTX_get_quiet_shutdown Returns the 'quiet shutdown' setting of $ctx. my $rv = Net::SSLeay::CTX_get_quiet_shutdown($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: (integer) the current setting Check openssl doc L =item * CTX_get_read_ahead my $rv = Net::SSLeay::CTX_get_read_ahead($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: (integer) read_ahead value =item * CTX_get_session_cache_mode Returns the currently used cache mode (bitmask). my $rv = Net::SSLeay::CTX_get_session_cache_mode($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: mode (bitmask) B SESS_CACHE_OFF and other constants are not available in Net-SSLeay-1.82 and before. If the constants are not available, the following values have historically been correct. You are strongly encouraged to B for the current values. #to decode the return value (bitmask) use: 0x0000 corresponds to SSL_SESS_CACHE_OFF 0x0001 corresponds to SSL_SESS_CACHE_CLIENT 0x0002 corresponds to SSL_SESS_CACHE_SERVER 0x0080 corresponds to SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0100 corresponds to SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0200 corresponds to SSL_SESS_CACHE_NO_INTERNAL_STORE (note: some of the bits might not be supported by older openssl versions) Check openssl doc L =item * CTX_set_session_cache_mode Enables/disables session caching by setting the operational mode for $ctx to $mode. my $rv = Net::SSLeay::CTX_set_session_cache_mode($ctx, $mode); # $ctx - value corresponding to openssl's SSL_CTX structure # $mode - mode (bitmask) # # returns: previously set cache mode For bitmask details see L (above). Check openssl doc L =item * CTX_get_timeout Returns the currently set timeout value for $ctx. my $rv = Net::SSLeay::CTX_get_timeout($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: timeout in seconds Check openssl doc L =item * CTX_get_verify_depth Returns the verification depth limit currently set in $ctx. If no limit has been explicitly set, -1 is returned and the default value will be used.", my $rv = Net::SSLeay::CTX_get_verify_depth($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: depth limit currently set in $ctx, -1 if no limit has been explicitly set Check openssl doc L =item * CTX_get_verify_mode Returns the verification mode (bitmask) currently set in $ctx. my $rv = Net::SSLeay::CTX_get_verify_mode($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: mode (bitmask) For bitmask details see L. Check openssl doc L =item * CTX_set_verify Sets the verification flags for $ctx to be $mode and specifies the verify_callback function to be used. Net::SSLeay::CTX_set_verify($ctx, $mode, $callback); # $ctx - value corresponding to openssl's SSL_CTX structure # $mode - mode (bitmask), see OpenSSL manual # $callback - [optional] reference to perl callback function # # returns: no return value Check openssl doc L =item * CTX_set_post_handshake_auth B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Enable the Post-Handshake Authentication extension to be added to the ClientHello such that post-handshake authentication can be requested by the server. Net::SSLeay::CTX_set_posthandshake_auth($ctx, $val); # $ctx - value corresponding to openssl's SSL_CTX structure # $val - 0 then the extension is not sent, otherwise it is # # returns: no return value Check openssl doc L =item * CTX_load_verify_locations Specifies the locations for $ctx, at which CA certificates for verification purposes are located. The certificates available via $CAfile and $CApath are trusted. my $rv = Net::SSLeay::CTX_load_verify_locations($ctx, $CAfile, $CApath); # $ctx - value corresponding to openssl's SSL_CTX structure # $CAfile - (string) file of CA certificates in PEM format, the file can contain several CA certificates (or '') # $CApath - (string) directory containing CA certificates in PEM format (or '') # # returns: 1 on success, 0 on failure (check the error stack to find out the reason) Check openssl doc L =item * CTX_need_tmp_RSA Return the result of C my $rv = Net::SSLeay::CTX_need_tmp_RSA($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: result of SSL_CTRL_NEED_TMP_RSA command Not available with OpenSSL 1.1 and later. =item * CTX_new The same as L my $rv = Net::SSLeay::CTX_new(); # # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) Check openssl doc L Not available with OpenSSL 1.1 and later. =item * CTX_v2_new Creates a new SSL_CTX object - based on SSLv2_method() - as framework to establish TLS/SSL enabled connections. my $rv = Net::SSLeay::CTX_v2_new(); # # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) =item * CTX_v23_new Creates a new SSL_CTX object - based on SSLv23_method() - as framework to establish TLS/SSL enabled connections. my $rv = Net::SSLeay::CTX_v23_new(); # # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) =item * CTX_v3_new Creates a new SSL_CTX object - based on SSLv3_method() - as framework to establish TLS/SSL enabled connections. my $rv = Net::SSLeay::CTX_v3_new(); # # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) =item * CTX_tlsv1_new Creates a new SSL_CTX object - based on TLSv1_method() - as framework to establish TLS/SSL enabled connections. my $rv = Net::SSLeay::CTX_tlsv1_new(); # # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) =item * CTX_tlsv1_1_new Creates a new SSL_CTX object - based on TLSv1_1_method() - as framework to establish TLS/SSL enabled connections. Only available where supported by the underlying openssl. my $rv = Net::SSLeay::CTX_tlsv1_1_new(); # # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) =item * CTX_tlsv1_2_new Creates a new SSL_CTX object - based on TLSv1_2_method() - as framework to establish TLS/SSL enabled connections. Only available where supported by the underlying openssl. my $rv = Net::SSLeay::CTX_tlsv1_2_new(); # # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) =item * CTX_new_with_method Creates a new SSL_CTX object based on $meth method my $rv = Net::SSLeay::CTX_new_with_method($meth); # $meth - value corresponding to openssl's SSL_METHOD structure # # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) #example my $ctx = Net::SSLeay::CTX_new_with_method(&Net::SSLeay::TLSv1_method); Check openssl doc L =item * CTX_set_min_proto_version, CTX_set_max_proto_version, set_min_proto_version and set_max_proto_version, B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0 or LibreSSL 2.6.0 Set the minimum and maximum supported protocol for $ctx or $ssl. my $rv = Net::SSLeay::CTX_set_min_proto_version($ctx, $version) # $ctx - value corresponding to openssl's SSL_CTX structure # $version - (integer) constat version value or 0 for automatic lowest or highest value # # returns: 1 on success, 0 on failure #example: allow only TLS 1.2 for a SSL_CTX my $rv_min = Net::SSLeay::CTX_set_min_proto_version($ctx, Net::SSLeay::TLS1_2_VERSION()); my $rv_max = Net::SSLeay::CTX_set_max_proto_version($ctx, Net::SSLeay::TLS1_2_VERSION()); #example: allow only TLS 1.1 for a SSL my $rv_min = Net::SSLeay::set_min_proto_version($ssl, Net::SSLeay::TLS1_1_VERSION()); my $rv_max = Net::SSLeay::set_max_proto_version($ssl, Net::SSLeay::TLS1_1_VERSION()); Check openssl doc L =item * CTX_get_min_proto_version, CTX_get_max_proto_version, get_min_proto_version and get_max_proto_version, B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0g Get the minimum and maximum supported protocol for $ctx or $ssl. my $version = Net::SSLeay::CTX_get_min_proto_version($ctx) # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: 0 automatic lowest or highest value, configured value otherwise Check openssl doc L =item * CTX_remove_session Removes the session $ses from the context $ctx. my $rv = Net::SSLeay::CTX_remove_session($ctx, $ses); # $ctx - value corresponding to openssl's SSL_CTX structure # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * CTX_sess_accept my $rv = Net::SSLeay::CTX_sess_accept($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of started SSL/TLS handshakes in server mode Check openssl doc L =item * CTX_sess_accept_good my $rv = Net::SSLeay::CTX_sess_accept_good($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of successfully established SSL/TLS sessions in server mode Check openssl doc L =item * CTX_sess_accept_renegotiate my $rv = Net::SSLeay::CTX_sess_accept_renegotiate($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of start renegotiations in server mode Check openssl doc L =item * CTX_sess_cache_full my $rv = Net::SSLeay::CTX_sess_cache_full($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of sessions that were removed because the maximum session cache size was exceeded Check openssl doc L =item * CTX_sess_cb_hits my $rv = Net::SSLeay::CTX_sess_cb_hits($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of successfully retrieved sessions from the external session cache in server mode Check openssl doc L =item * CTX_sess_connect my $rv = Net::SSLeay::CTX_sess_connect($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of started SSL/TLS handshakes in client mode Check openssl doc L =item * CTX_sess_connect_good my $rv = Net::SSLeay::CTX_sess_connect_good($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of successfully established SSL/TLS sessions in client mode Check openssl doc L =item * CTX_sess_connect_renegotiate my $rv = Net::SSLeay::CTX_sess_connect_renegotiate($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of start renegotiations in client mode Check openssl doc L =item * CTX_sess_get_cache_size Returns the currently valid session cache size. my $rv = Net::SSLeay::CTX_sess_get_cache_size($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: current size Check openssl doc L =item * CTX_sess_hits my $rv = Net::SSLeay::CTX_sess_hits($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of successfully reused sessions Check openssl doc L =item * CTX_sess_misses my $rv = Net::SSLeay::CTX_sess_misses($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of sessions proposed by clients that were not found in the internal session cache in server mode Check openssl doc L =item * CTX_sess_number my $rv = Net::SSLeay::CTX_sess_number($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: current number of sessions in the internal session cache Check openssl doc L =item * CTX_sess_set_cache_size Sets the size of the internal session cache of context $ctx to $size. Net::SSLeay::CTX_sess_set_cache_size($ctx, $size); # $ctx - value corresponding to openssl's SSL_CTX structure # $size - cache size (0 = unlimited) # # returns: previously valid size Check openssl doc L =item * CTX_sess_timeouts Returns the number of sessions proposed by clients and either found in the internal or external session cache in server mode, but that were invalid due to timeout. These sessions are not included in the SSL_CTX_sess_hits count. my $rv = Net::SSLeay::CTX_sess_timeouts($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: number of sessions Check openssl doc L =item * CTX_sess_set_new_cb B not available in Net-SSLeay-1.85 and before Sets the callback function, which is automatically called whenever a new session was negotiated. Net::SSLeay::CTX_sess_set_new_cb($ctx, $func); # $ctx - value corresponding to openssl's SSL_CTX structure # $func - perl reference to callback function # # returns: no return value Check openssl doc L =item * CTX_sess_set_remove_cb B not available in Net-SSLeay-1.85 and before Sets the callback function, which is automatically called whenever a session is removed by the SSL engine. Net::SSLeay::CTX_sess_set_remove_cb($ctx, $func); # $ctx - value corresponding to openssl's SSL_CTX structure # $func - perl reference to callback function # # returns: no return value Check openssl doc L =item * CTX_sessions Returns a pointer to the lhash databases containing the internal session cache for ctx. my $rv = Net::SSLeay::CTX_sessions($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: value corresponding to openssl's LHASH structure (0 on failure) Check openssl doc L =item * CTX_set1_param Applies X509 verification parameters $vpm on $ctx my $rv = Net::SSLeay::CTX_set1_param($ctx, $vpm); # $ctx - value corresponding to openssl's SSL_CTX structure # $vpm - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * CTX_set_cert_store Sets/replaces the certificate verification storage of $ctx to/with $store. Net::SSLeay::CTX_set_cert_store($ctx, $store); # $ctx - value corresponding to openssl's SSL_CTX structure # $store - value corresponding to openssl's X509_STORE structure # # returns: no return value Check openssl doc L =item * CTX_set_cert_verify_callback Sets the verification callback function for $ctx. SSL objects that are created from $ctx inherit the setting valid at the time when C is called. Net::SSLeay::CTX_set_cert_verify_callback($ctx, $func, $data); # $ctx - value corresponding to openssl's SSL_CTX structure # $func - perl reference to callback function # $data - [optional] data that will be passed to callback function when invoked # # returns: no return value Check openssl doc L =item * CTX_set_cipher_list Sets the list of available ciphers for $ctx using the control string $str. The list of ciphers is inherited by all ssl objects created from $ctx. my $rv = Net::SSLeay::CTX_set_cipher_list($s, $str); # $s - value corresponding to openssl's SSL_CTX structure # $str - (string) cipher list e.g. '3DES:+RSA' # # returns: 1 if any cipher could be selected and 0 on complete failure The format of $str is described in L Check openssl doc L =item * CTX_set_ciphersuites B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Configure the available TLSv1.3 ciphersuites. my $rv = Net::SSLeay::CTX_set_ciphersuites($ctx, $str); # $ctx - value corresponding to openssl's SSL_CTX structure # $str - colon (":") separated list of TLSv1.3 ciphersuite names in order of preference # # returns: (integer) 1 if the requested ciphersuite list was configured, and 0 otherwise Check openssl doc L =item * CTX_set_client_CA_list Sets the list of CAs sent to the client when requesting a client certificate for $ctx. Net::SSLeay::CTX_set_client_CA_list($ctx, $list); # $ctx - value corresponding to openssl's SSL_CTX structure # $list - value corresponding to openssl's X509_NAME_STACK structure # # returns: no return value Check openssl doc L =item * CTX_set_default_passwd_cb Sets the default password callback called when loading/storing a PEM certificate with encryption. Net::SSLeay::CTX_set_default_passwd_cb($ctx, $func); # $ctx - value corresponding to openssl's SSL_CTX structure # $func - perl reference to callback function # # returns: no return value Check openssl doc L =item * CTX_set_default_passwd_cb_userdata Sets a pointer to userdata which will be provided to the password callback on invocation. Net::SSLeay::CTX_set_default_passwd_cb_userdata($ctx, $userdata); # $ctx - value corresponding to openssl's SSL_CTX structure # $userdata - data that will be passed to callback function when invoked # # returns: no return value Check openssl doc L =item * CTX_set_default_verify_paths ??? (more info needed) my $rv = Net::SSLeay::CTX_set_default_verify_paths($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: 1 on success, 0 on failure =item * CTX_set_ex_data Is used to store application data at $data for $idx into the $ctx object. my $rv = Net::SSLeay::CTX_set_ex_data($ssl, $idx, $data); # $ssl - value corresponding to openssl's SSL_CTX structure # $idx - (integer) ??? # $data - (pointer) ??? # # returns: 1 on success, 0 on failure Check openssl doc L =item * CTX_set_purpose my $rv = Net::SSLeay::CTX_set_purpose($s, $purpose); # $s - value corresponding to openssl's SSL_CTX structure # $purpose - (integer) purpose identifier # # returns: 1 on success, 0 on failure #avainable purpose identifier 1 - X509_PURPOSE_SSL_CLIENT 2 - X509_PURPOSE_SSL_SERVER 3 - X509_PURPOSE_NS_SSL_SERVER 4 - X509_PURPOSE_SMIME_SIGN 5 - X509_PURPOSE_SMIME_ENCRYPT 6 - X509_PURPOSE_CRL_SIGN 7 - X509_PURPOSE_ANY 8 - X509_PURPOSE_OCSP_HELPER 9 - X509_PURPOSE_TIMESTAMP_SIGN #or use corresponding constants $purpose = &Net::SSLeay::X509_PURPOSE_SSL_CLIENT; ... $purpose = &Net::SSLeay::X509_PURPOSE_TIMESTAMP_SIGN; =item * CTX_set_quiet_shutdown Sets the 'quiet shutdown' flag for $ctx to be mode. SSL objects created from $ctx inherit the mode valid at the time C is called. Net::SSLeay::CTX_set_quiet_shutdown($ctx, $mode); # $ctx - value corresponding to openssl's SSL_CTX structure # $mode - 0 or 1 # # returns: no return value Check openssl doc L =item * CTX_set_read_ahead my $rv = Net::SSLeay::CTX_set_read_ahead($ctx, $val); # $ctx - value corresponding to openssl's SSL_CTX structure # $val - read_ahead value to be set # # returns: the original read_ahead value =item * CTX_set_session_id_context Sets the context $sid_ctx of length $sid_ctx_len within which a session can be reused for the $ctx object. my $rv = Net::SSLeay::CTX_set_session_id_context($ctx, $sid_ctx, $sid_ctx_len); # $ctx - value corresponding to openssl's SSL_CTX structure # $sid_ctx - data buffer # $sid_ctx_len - length of data in $sid_ctx # # returns: 1 on success, 0 on failure (the error is logged to the error stack) Check openssl doc L =item * CTX_set_ssl_version Sets a new default TLS/SSL method for SSL objects newly created from this $ctx. SSL objects already created with C are not affected, except when C is being called. my $rv = Net::SSLeay::CTX_set_ssl_version($ctx, $meth); # $ctx - value corresponding to openssl's SSL_CTX structure # $meth - value corresponding to openssl's SSL_METHOD structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * CTX_set_timeout Sets the timeout for newly created sessions for $ctx to $t. The timeout value $t must be given in seconds. my $rv = Net::SSLeay::CTX_set_timeout($ctx, $t); # $ctx - value corresponding to openssl's SSL_CTX structure # $t - timeout in seconds # # returns: previously set timeout value Check openssl doc L =item * CTX_set_tmp_dh Sets DH parameters to be used to be $dh. The key is inherited by all ssl objects created from $ctx. my $rv = Net::SSLeay::CTX_set_tmp_dh($ctx, $dh); # $ctx - value corresponding to openssl's SSL_CTX structure # $dh - value corresponding to openssl's DH structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * CTX_set_tmp_dh_callback Sets the callback function for $ctx to be used when a DH parameters are required to $tmp_dh_callback. Net::SSLeay::CTX_set_tmp_dh_callback($ctx, $tmp_dh_callback); # $ctx - value corresponding to openssl's SSL_CTX structure # tmp_dh_callback - (function pointer) ??? # # returns: no return value Check openssl doc L =item * CTX_set_tmp_rsa Sets the temporary/ephemeral RSA key to be used to be $rsa. my $rv = Net::SSLeay::CTX_set_tmp_rsa($ctx, $rsa); # $ctx - value corresponding to openssl's SSL_CTX structure # $rsa - value corresponding to openssl's RSA structure # # returns: 1 on success, 0 on failure Check openssl doc L Not available with OpenSSL 1.1 and later. =item * CTX_set_tmp_rsa_callback Sets the callback function for ctx to be used when a temporary/ephemeral RSA key is required to $tmp_rsa_callback. ??? (does this function really work?) Net::SSLeay::CTX_set_tmp_rsa_callback($ctx, $tmp_rsa_callback); # $ctx - value corresponding to openssl's SSL_CTX structure # $tmp_rsa_callback - (function pointer) ??? # # returns: no return value Check openssl doc L Not available with OpenSSL 1.1 and later. =item * CTX_set_trust my $rv = Net::SSLeay::CTX_set_trust($s, $trust); # $s - value corresponding to openssl's SSL_CTX structure # $trust - (integer) trust identifier # # returns: the original value #available trust identifiers 1 - X509_TRUST_COMPAT 2 - X509_TRUST_SSL_CLIENT 3 - X509_TRUST_SSL_SERVER 4 - X509_TRUST_EMAIL 5 - X509_TRUST_OBJECT_SIGN 6 - X509_TRUST_OCSP_SIGN 7 - X509_TRUST_OCSP_REQUEST 8 - X509_TRUST_TSA #or use corresponding constants $trust = &Net::SSLeay::X509_TRUST_COMPAT; ... $trust = &Net::SSLeay::X509_TRUST_TSA; =item * CTX_set_verify_depth Sets the maximum depth for the certificate chain verification that shall be allowed for ctx. Net::SSLeay::CTX_set_verify_depth($ctx, $depth); # $ctx - value corresponding to openssl's SSL_CTX structure # $depth - max. depth # # returns: no return value Check openssl doc L =item * CTX_use_PKCS12_file Adds the certificate and private key from PKCS12 file $p12filename to $ctx. my $rv = Net::SSLeay::CTX_use_PKCS12_file($ctx, $p12filename, $password); # $ctx - value corresponding to openssl's SSL_CTX structure # $p12filename - (string) filename # $password - (string) password to decrypt private key # # returns: 1 on success, 0 on failure =item * CTX_use_PrivateKey Adds the private key $pkey to $ctx. my $rv = Net::SSLeay::CTX_use_PrivateKey($ctx, $pkey); # $ctx - value corresponding to openssl's SSL_CTX structure # $pkey - value corresponding to openssl's EVP_PKEY structure # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * CTX_use_PrivateKey_file Adds the first private key found in $file to $ctx. my $rv = Net::SSLeay::CTX_use_PrivateKey_file($ctx, $file, $type); # $ctx - value corresponding to openssl's SSL_CTX structure # $file - (string) file name # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * CTX_use_RSAPrivateKey Adds the RSA private key $rsa to $ctx. my $rv = Net::SSLeay::CTX_use_RSAPrivateKey($ctx, $rsa); # $ctx - value corresponding to openssl's SSL_CTX structure # $rsa - value corresponding to openssl's RSA structure # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * CTX_use_RSAPrivateKey_file Adds the first RSA private key found in $file to $ctx. my $rv = Net::SSLeay::CTX_use_RSAPrivateKey_file($ctx, $file, $type); # $ctx - value corresponding to openssl's SSL_CTX structure # $file - (string) file name # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 # # returns: 1 on success, otherwise check out the error stack to find out the reason =item * CTX_use_certificate Loads the certificate $x into $ctx my $rv = Net::SSLeay::CTX_use_certificate($ctx, $x); # $ctx - value corresponding to openssl's SSL_CTX structure # $x - value corresponding to openssl's X509 structure # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * CTX_use_certificate_chain_file Loads a certificate chain from $file into $ctx. The certificates must be in PEM format and must be sorted starting with the subject's certificate (actual client or server certificate), followed by intermediate CA certificates if applicable, and ending at the highest level (root) CA. my $rv = Net::SSLeay::CTX_use_certificate_chain_file($ctx, $file); # $ctx - value corresponding to openssl's SSL_CTX structure # $file - (string) file name # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * CTX_use_certificate_file Loads the first certificate stored in $file into $ctx. my $rv = Net::SSLeay::CTX_use_certificate_file($ctx, $file, $type); # $ctx - value corresponding to openssl's SSL_CTX structure # $file - (string) file name # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * CTX_get_security_level B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL Returns the security level associated with $ctx. my $level = Net::SSLeay::CTX_get_security_level($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: (integer) current security level Check openssl doc L =item * CTX_set_security_level B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL Sets the security level associated with $ctx to $level. Net::SSLeay::CTX_set_security_level($ctx, $level); # $ssl - value corresponding to openssl's SSL_CTX structure # $level - new security level # # returns: no return value Check openssl doc L =item * CTX_set_num_tickets B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Set number of TLSv1.3 session tickets that will be sent to a client. my $rv = Net::SSLeay::CTX_set_num_tickets($ctx, $number_of_tickets); # $ctx - value corresponding to openssl's SSL_CTX structure # $number_of_tickets - number of tickets to send # # returns: 1 on success, 0 on failure Set to zero if you do not no want to support a session resumption. Check openssl doc L =item * CTX_get_num_tickets B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Get number of TLSv1.3 session tickets that will be sent to a client. my $number_of_tickets = Net::SSLeay::CTX_get_num_tickets($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: (integer) number of tickets to send Check openssl doc L =back =head3 Low level API: SSL_* related functions B Please note that the function described in this chapter have "SSL_" part stripped from their original openssl names. =over =item * new Creates a new SSL structure which is needed to hold the data for a TLS/SSL connection. The new structure inherits the settings of the underlying context $ctx: connection method (SSLv2/v3/TLSv1), options, verification settings, timeout settings. my $rv = Net::SSLeay::new($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: value corresponding to openssl's SSL structure (0 on failure) Check openssl doc L =item * accept Waits for a TLS/SSL client to initiate the TLS/SSL handshake. The communication channel must already have been set and assigned to the ssl by setting an underlying BIO. my $rv = Net::SSLeay::accept($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 1 = success, 0 = handshake not successful, <0 = fatal error during handshake Check openssl doc L =item * add_client_CA Adds the CA name extracted from cacert to the list of CAs sent to the client when requesting a client certificate for the chosen ssl, overriding the setting valid for ssl's SSL_CTX object. my $rv = Net::SSLeay::add_client_CA($ssl, $x); # $ssl - value corresponding to openssl's SSL structure # $x - value corresponding to openssl's X509 structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * callback_ctrl ??? (more info needed) my $rv = Net::SSLeay::callback_ctrl($ssl, $cmd, $fp); # $ssl - value corresponding to openssl's SSL structure # $cmd - (integer) command id # $fp - (function pointer) ??? # # returns: ??? Check openssl doc L =item * check_private_key Checks the consistency of a private key with the corresponding certificate loaded into $ssl my $rv = Net::SSLeay::check_private_key($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * clear Reset SSL object to allow another connection. Net::SSLeay::clear($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: no return value Check openssl doc L =item * connect Initiate the TLS/SSL handshake with an TLS/SSL server. my $rv = Net::SSLeay::connect($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 1 = success, 0 = handshake not successful, <0 = fatal error during handshake Check openssl doc L =item * copy_session_id Copies the session structure fro $from to $to (+ also the private key and certificate associated with $from). Net::SSLeay::copy_session_id($to, $from); # $to - value corresponding to openssl's SSL structure # $from - value corresponding to openssl's SSL structure # # returns: no return value =item * ctrl Internal handling function for SSL objects. B openssl doc says: This function should never be called directly! my $rv = Net::SSLeay::ctrl($ssl, $cmd, $larg, $parg); # $ssl - value corresponding to openssl's SSL structure # $cmd - (integer) command id # $larg - (integer) long ??? # $parg - (string/pointer) ??? # # returns: (long) result of given command ??? For more details about valid $cmd values check L. Check openssl doc L =item * do_handshake Will wait for a SSL/TLS handshake to take place. If the connection is in client mode, the handshake will be started. The handshake routines may have to be explicitly set in advance using either SSL_set_connect_state or SSL_set_accept_state(3). my $rv = Net::SSLeay::do_handshake($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 1 = success, 0 = handshake not successful, <0 = fatal error during handshake Check openssl doc L =item * dup Returns a duplicate of $ssl. my $rv = Net::SSLeay::dup($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's SSL structure (0 on failure) =item * free Free an allocated SSL structure. Net::SSLeay::free($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: no return value Check openssl doc L =item * get0_param B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 Returns the current verification parameters. my $vpm = Net::SSLeay::get0_param($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's X509_VERIFY_PARAM structure Check openssl doc L =item * get_SSL_CTX Returns a pointer to the SSL_CTX object, from which $ssl was created with Net::SSLeay::new. my $rv = Net::SSLeay::get_SSL_CTX($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) Check openssl doc L =item * set_SSL_CTX Sets the SSL_CTX the corresponds to an SSL session. my $the_ssl_ctx = Net::SSLeay::set_SSL_CTX($ssl, $ssl_ctx); # $ssl - value corresponding to openssl's SSL structure # $ssl_ctx - Change the ssl object to the given ssl_ctx # # returns - the ssl_ctx =item * get_app_data Can be used to get application defined value/data. my $rv = Net::SSLeay::get_app_data($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: string/buffer/pointer ??? =item * set_app_data Can be used to set some application defined value/data. my $rv = Net::SSLeay::set_app_data($ssl, $arg); # $ssl - value corresponding to openssl's SSL structure # $arg - (string/buffer/pointer ???) data # # returns: ??? =item * get_certificate Gets X509 certificate from an established SSL connection. my $rv = Net::SSLeay::get_certificate($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's X509 structure (0 on failure) =item * get_cipher Obtains the name of the currently used cipher. my $rv = Net::SSLeay::get_cipher($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (string) cipher name e.g. 'DHE-RSA-AES256-SHA' or '', when no session has been established. Check openssl doc L =item * get_cipher_bits Obtain the number of secret/algorithm bits used. my $rv = Net::SSLeay::get_cipher_bits($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: number of secret bits used by current cipher Check openssl doc L and L =item * get_cipher_list Returns the name (string) of the SSL_CIPHER listed for $ssl with priority $n. my $rv = Net::SSLeay::get_cipher_list($ssl, $n); # $ssl - value corresponding to openssl's SSL structure # $n - (integer) priority # # returns: (string) cipher name e.g. 'EDH-DSS-DES-CBC3-SHA' or '' in case of error Call Net::SSLeay::get_cipher_list with priority starting from 0 to obtain the sorted list of available ciphers, until '' is returned: my $priority = 0; while (my $c = Net::SSLeay::get_cipher_list($ssl, $priority)) { print "cipher[$priority] = $c\n"; $priority++; } Check openssl doc L =item * get_client_CA_list Returns the list of client CAs explicitly set for $ssl using C or $ssl's SSL_CTX object with C, when in server mode. In client mode, returns the list of client CAs sent from the server, if any. my $rv = Net::SSLeay::get_client_CA_list($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's STACK_OF(X509_NAME) structure (0 on failure) Check openssl doc L =item * get_current_cipher Returns the cipher actually used. my $rv = Net::SSLeay::get_current_cipher($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's SSL_CIPHER structure (0 on failure) Check openssl doc L =item * get_default_timeout Returns the default timeout value assigned to SSL_SESSION objects negotiated for the protocol valid for $ssl. my $rv = Net::SSLeay::get_default_timeout($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (long) timeout in seconds Check openssl doc L =item * get_error Returns a result code for a preceding call to C, C, C, C, C or C on $ssl. my $rv = Net::SSLeay::get_error($ssl, $ret); # $ssl - value corresponding to openssl's SSL structure # $ret - return value of preceding TLS/SSL I/O operation # # returns: result code, which is one of the following values: # 0 - SSL_ERROR_NONE # 1 - SSL_ERROR_SSL # 2 - SSL_ERROR_WANT_READ # 3 - SSL_ERROR_WANT_WRITE # 4 - SSL_ERROR_WANT_X509_LOOKUP # 5 - SSL_ERROR_SYSCALL # 6 - SSL_ERROR_ZERO_RETURN # 7 - SSL_ERROR_WANT_CONNECT # 8 - SSL_ERROR_WANT_ACCEPT Check openssl doc L =item * get_ex_data Is used to retrieve the information for $idx from $ssl. my $rv = Net::SSLeay::get_ex_data($ssl, $idx); # $ssl - value corresponding to openssl's SSL structure # $idx - (integer) index for application specific data # # returns: pointer to ??? Check openssl doc L =item * set_ex_data Is used to store application data at $data for $idx into the $ssl object. my $rv = Net::SSLeay::set_ex_data($ssl, $idx, $data); # $ssl - value corresponding to openssl's SSL structure # $idx - (integer) ??? # $data - (pointer) ??? # # returns: 1 on success, 0 on failure Check openssl doc L =item * get_ex_new_index Is used to register a new index for application specific data. my $rv = Net::SSLeay::get_ex_new_index($argl, $argp, $new_func, $dup_func, $free_func); # $argl - (long) ??? # $argp - (pointer) ??? # $new_func - function pointer ??? (CRYPTO_EX_new *) # $dup_func - function pointer ??? (CRYPTO_EX_dup *) # $free_func - function pointer ??? (CRYPTO_EX_free *) # # returns: (integer) ??? Check openssl doc L =item * get_fd Returns the file descriptor which is linked to $ssl. my $rv = Net::SSLeay::get_fd($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: file descriptor (>=0) or -1 on failure Check openssl doc L =item * get_finished Obtains the latest 'Finished' message sent to the peer. Return value is zero if there's been no Finished message yet. Default count is 2*EVP_MAX_MD_SIZE that is long enough for all possible Finish messages. If you supply a non-default count, the resulting return value may be longer than returned buf's length. my $rv = Net::SSLeay::get_finished($ssl, $buf, $count); # $ssl - value corresponding to openssl's SSL structure # $buf - buffer where the returned data will be stored # $count - [optional] max size of return data - default is 2*EVP_MAX_MD_SIZE # # returns: length of latest Finished message =item * get_peer_finished Obtains the latest 'Finished' message expected from the peer. Parameters and return value are similar to get_finished(). my $rv = Net::SSLeay::get_peer_finished($ssl, $buf, $count); # $ssl - value corresponding to openssl's SSL structure # $buf - buffer where the returned data will be stored # $count - [optional] max size of return data - default is 2*EVP_MAX_MD_SIZE # # returns: length of latest Finished message =item * get_keyblock_size Gets the length of the TLS keyblock. B Does not exactly correspond to any low level API function. my $rv = Net::SSLeay::get_keyblock_size($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: keyblock size, -1 on error =item * get_mode Returns the mode (bitmask) set for $ssl. my $rv = Net::SSLeay::get_mode($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: mode (bitmask) To decode the return value (bitmask) see documentation for L. Check openssl doc L =item * set_mode Adds the mode set via bitmask in $mode to $ssl. Options already set before are not cleared. my $rv = Net::SSLeay::set_mode($ssl, $mode); # $ssl - value corresponding to openssl's SSL structure # $mode - mode (bitmask) # # returns: the new mode bitmask after adding $mode For $mode bitmask details see L. Check openssl doc L =item * get_options Returns the options (bitmask) set for $ssl. my $rv = Net::SSLeay::get_options($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: options (bitmask) To decode the return value (bitmask) see documentation for L. Check openssl doc L =item * set_options Adds the options set via bitmask in $options to $ssl. Options already set before are not cleared! Net::SSLeay::set_options($ssl, $options); # $ssl - value corresponding to openssl's SSL structure # $options - options (bitmask) # # returns: the new options bitmask after adding $options For $options bitmask details see L. Check openssl doc L =item * get_peer_certificate Get the X509 certificate of the peer. my $rv = Net::SSLeay::get_peer_certificate($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's X509 structure (0 on failure) Check openssl doc L =item * get_peer_cert_chain Get the certificate chain of the peer as an array of X509 structures. my @rv = Net::SSLeay::get_peer_cert_chain($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: list of X509 structures Check openssl doc L =item * get_quiet_shutdown Returns the 'quiet shutdown' setting of ssl. my $rv = Net::SSLeay::get_quiet_shutdown($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) current 'quiet shutdown' value Check openssl doc L =item * get_rbio Get 'read' BIO linked to an SSL object $ssl. my $rv = Net::SSLeay::get_rbio($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's BIO structure (0 on failure) Check openssl doc L =item * get_read_ahead my $rv = Net::SSLeay::get_read_ahead($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) read_ahead value =item * set_read_ahead Net::SSLeay::set_read_ahead($ssl, $val); # $ssl - value corresponding to openssl's SSL structure # $val - read_ahead value to be set # # returns: the original read_ahead value =item * get_security_level B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL Returns the security level associated with $ssl. my $level = Net::SSLeay::get_security_level($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) current security level Check openssl doc L =item * set_security_level B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL Sets the security level associated with $ssl to $level. Net::SSLeay::set_security_level($ssl, $level); # $ssl - value corresponding to openssl's SSL structure # $level - new security level # # returns: no return value Check openssl doc L =item * set_num_tickets B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Set number of TLSv1.3 session tickets that will be sent to a client. my $rv = Net::SSLeay::set_num_tickets($ssl, $number_of_tickets); # $ssl - value corresponding to openssl's SSL structure # $number_of_tickets - number of tickets to send # # returns: 1 on success, 0 on failure Set to zero if you do not no want to support a session resumption. Check openssl doc L =item * get_num_tickets B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Get number of TLSv1.3 session tickets that will be sent to a client. my $number_of_tickets = Net::SSLeay::get_num_tickets($ctx); # $ctx - value corresponding to openssl's SSL structure # # returns: number of tickets to send Check openssl doc L =item * get_server_random Returns internal SSLv3 server_random value. Net::SSLeay::get_server_random($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: server_random value (binary data) =item * get_client_random B Does not exactly correspond to any low level API function Returns internal SSLv3 client_random value. Net::SSLeay::get_client_random($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: client_random value (binary data) =item * export_keying_material Returns keying material based on the string $label and optional $context. Note that with TLSv1.2 and lower, empty context (empty string) and undefined context (no value or 'undef') will return different values. my $out = Net::SSLeay::export_keying_material($ssl, $olen, $label, $context); # $ssl - value corresponding to openssl's SSL structure # $olen - number of bytes to return # $label - application specific label # $context - [optional] context - default is undef for no context # # returns: keying material (binary data) or undef on error Check openssl doc L =item * get_session Retrieve TLS/SSL session data used in $ssl. The reference count of the SSL_SESSION is NOT incremented. my $rv = Net::SSLeay::get_session($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's SSL_SESSION structure (0 on failure) Check openssl doc L =item * SSL_get0_session The alias for L (note that the name is C NOT C). my $rv = Net::SSLeay::SSL_get0_session(); =item * get1_session Returns a pointer to the SSL_SESSION actually used in $ssl. The reference count of the SSL_SESSION is incremented by 1. my $rv = Net::SSLeay::get1_session($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's SSL_SESSION structure (0 on failure) Check openssl doc L =item * get_shared_ciphers Returns string with a list (colon ':' separated) of ciphers shared between client and server within SSL session $ssl. my $rv = Net::SSLeay::get_shared_ciphers() # # returns: string like 'ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:...' =item * get_shutdown Returns the shutdown mode of $ssl. my $rv = Net::SSLeay::get_shutdown($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: shutdown mode (bitmask) of ssl #to decode the return value (bitmask) use: 0 - No shutdown setting, yet 1 - SSL_SENT_SHUTDOWN 2 - SSL_RECEIVED_SHUTDOWN Check openssl doc L =item * get_ssl_method Returns a function pointer to the TLS/SSL method set in $ssl. my $rv = Net::SSLeay::get_ssl_method($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) Check openssl doc L =item * in_init, in_before, is_init_finished, in_connect_init, in_accept_init B not available in Net-SSLeay-1.85 and before. Retrieve information about the handshake state machine. All functions take $ssl as the only argument and return 0 or 1. These functions are recommended over get_state() and state(). my $rv = Net::SSLeay::is_init_finished($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: All functions return 1 or 0 Check openssl doc L =item * get_state B OpenSSL 1.1.0 and later use different constants which are not made available. Use is_init_finished() and related functions instead. Returns the SSL connection state. my $rv = Net::SSLeay::get_state($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) state value # to decode the returned state check: # SSL_ST_* constants in openssl/ssl.h # SSL2_ST_* constants in openssl/ssl2.h # SSL23_ST_* constants in openssl/ssl23.h # SSL3_ST_* + DTLS1_ST_* constants in openssl/ssl3.h =item * state Exactly the same as L. my $rv = Net::SSLeay::state($ssl); =item * set_state Sets the SSL connection state. Net::SSLeay::set_state($ssl,Net::SSLeay::SSL_ST_ACCEPT()); Not available with OpenSSL 1.1 and later. =item * get_verify_depth Returns the verification depth limit currently set in $ssl. my $rv = Net::SSLeay::get_verify_depth($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: current depth or -1 if no limit has been explicitly set Check openssl doc L =item * set_verify_depth Sets the maximum depth for the certificate chain verification that shall be allowed for $ssl. Net::SSLeay::set_verify_depth($ssl, $depth); # $ssl - value corresponding to openssl's SSL structure # $depth - (integer) depth # # returns: no return value Check openssl doc L =item * get_verify_mode Returns the verification mode (bitmask) currently set in $ssl. my $rv = Net::SSLeay::get_verify_mode($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: mode (bitmask) To decode the return value (bitmask) see documentation for L. Check openssl doc L =item * set_verify Sets the verification flags for $ssl to be $mode and specifies the $verify_callback function to be used. Net::SSLeay::set_verify($ssl, $mode, $callback); # $ssl - value corresponding to openssl's SSL structure # $mode - mode (bitmask) # $callback - [optional] reference to perl callback function # # returns: no return value For $mode bitmask details see L. Check openssl doc L =item * set_post_handshake_auth B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Enable the Post-Handshake Authentication extension to be added to the ClientHello such that post-handshake authentication can be requested by the server. Net::SSLeay::set_posthandshake_auth($ssl, $val); # $ssl - value corresponding to openssl's SSL structure # $val - 0 then the extension is not sent, otherwise it is # # returns: no return value Check openssl doc L =item * verify_client_post_handshake B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL verify_client_post_handshake causes a CertificateRequest message to be sent by a server on the given ssl connection. my $rv = Net::SSLeay::verify_client_post_handshake($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 1 if the request succeeded, and 0 if the request failed. The error stack can be examined to determine the failure reason. Check openssl doc L =item * get_verify_result Returns the result of the verification of the X509 certificate presented by the peer, if any. my $rv = Net::SSLeay::get_verify_result($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) # 0 - X509_V_OK: ok # 2 - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: unable to get issuer certificate # 3 - X509_V_ERR_UNABLE_TO_GET_CRL: unable to get certificate CRL # 4 - X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: unable to decrypt certificate's signature # 5 - X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: unable to decrypt CRL's signature # 6 - X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: unable to decode issuer public key # 7 - X509_V_ERR_CERT_SIGNATURE_FAILURE: certificate signature failure # 8 - X509_V_ERR_CRL_SIGNATURE_FAILURE: CRL signature failure # 9 - X509_V_ERR_CERT_NOT_YET_VALID: certificate is not yet valid # 10 - X509_V_ERR_CERT_HAS_EXPIRED: certificate has expired # 11 - X509_V_ERR_CRL_NOT_YET_VALID: CRL is not yet valid # 12 - X509_V_ERR_CRL_HAS_EXPIRED: CRL has expired # 13 - X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: format error in certificate's notBefore field # 14 - X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: format error in certificate's notAfter field # 15 - X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: format error in CRL's lastUpdate field # 16 - X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: format error in CRL's nextUpdate field # 17 - X509_V_ERR_OUT_OF_MEM: out of memory # 18 - X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: self signed certificate # 19 - X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: self signed certificate in certificate chain # 20 - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate # 21 - X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: unable to verify the first certificate # 22 - X509_V_ERR_CERT_CHAIN_TOO_LONG: certificate chain too long # 23 - X509_V_ERR_CERT_REVOKED: certificate revoked # 24 - X509_V_ERR_INVALID_CA: invalid CA certificate # 25 - X509_V_ERR_PATH_LENGTH_EXCEEDED: path length constraint exceeded # 26 - X509_V_ERR_INVALID_PURPOSE: unsupported certificate purpose # 27 - X509_V_ERR_CERT_UNTRUSTED: certificate not trusted # 28 - X509_V_ERR_CERT_REJECTED: certificate rejected # 29 - X509_V_ERR_SUBJECT_ISSUER_MISMATCH: subject issuer mismatch # 30 - X509_V_ERR_AKID_SKID_MISMATCH: authority and subject key identifier mismatch # 31 - X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: authority and issuer serial number mismatch # 32 - X509_V_ERR_KEYUSAGE_NO_CERTSIGN:key usage does not include certificate signing # 50 - X509_V_ERR_APPLICATION_VERIFICATION: application verification failure Check openssl doc L =item * set_verify_result Override result of peer certificate verification. Net::SSLeay::set_verify_result($ssl, $v); # $ssl - value corresponding to openssl's SSL structure # $v - (integer) result value # # returns: no return value For more info about valid return values see L Check openssl doc L =item * get_wbio Get 'write' BIO linked to an SSL object $ssl. my $rv = Net::SSLeay::get_wbio($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: value corresponding to openssl's BIO structure (0 on failure) Check openssl doc L =item * load_client_CA_file Load X509 certificates from file (PEM formatted). my $rv = Net::SSLeay::load_client_CA_file($file); # $file - (string) file name # # returns: value corresponding to openssl's STACK_OF(X509_NAME) structure (0 on failure) Check openssl doc L =item * clear_num_renegotiations Executes SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS command on $ssl. my $rv = Net::SSLeay::clear_num_renegotiations($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: command result =item * need_tmp_RSA Executes SSL_CTRL_NEED_TMP_RSA command on $ssl. my $rv = Net::SSLeay::need_tmp_RSA($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: command result Not available with OpenSSL 1.1 and later. =item * num_renegotiations Executes SSL_CTRL_GET_NUM_RENEGOTIATIONS command on $ssl. my $rv = Net::SSLeay::num_renegotiations($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: command result =item * total_renegotiations Executes SSL_CTRL_GET_TOTAL_RENEGOTIATIONS command on $ssl. my $rv = Net::SSLeay::total_renegotiations($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: command result =item * peek Copies $max bytes from the specified $ssl into the returned value. In contrast to the C function, the data in the SSL buffer is unmodified after the SSL_peek() operation. Net::SSLeay::peek($ssl, $max); # $ssl - value corresponding to openssl's SSL structure # $max - [optional] max bytes to peek (integer) - default is 32768 # # in scalar context: data read from the TLS/SSL connection, undef on error # in list context: two-item array consisting of data read (undef on error), # and return code from SSL_peek(). =item * peek_ex B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Copies $max bytes from the specified $ssl into the returned value. In contrast to the C function, the data in the SSL buffer is unmodified after the SSL_peek_ex() operation. my($got, $rv) = Net::SSLeay::peek_ex($ssl, $max); # $ssl - value corresponding to openssl's SSL structure # $max - [optional] max bytes to peek (integer) - default is 32768 # # returns a list: two-item list consisting of data read (undef on error), # and return code from SSL_peek_ex(). Check openssl doc L =item * pending Obtain number of readable bytes buffered in $ssl object. my $rv = Net::SSLeay::pending($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: the number of bytes pending Check openssl doc L =item * has_pending B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL Returns 1 if $ssl has buffered data (whether processed or unprocessed) and 0 otherwise. my $rv = Net::SSLeay::has_pending($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) 1 or 0 Check openssl doc L =item * read Tries to read $max bytes from the specified $ssl. my $got = Net::SSLeay::read($ssl, $max); my($got, $rv) = Net::SSLeay::read($ssl, $max); # $ssl - value corresponding to openssl's SSL structure # $max - [optional] max bytes to read (integer) - default is 32768 # # returns: # in scalar context: data read from the TLS/SSL connection, undef on error # in list context: two-item array consisting of data read (undef on error), # and return code from SSL_read(). Check openssl doc L =item * read_ex B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Tries to read $max bytes from the specified $ssl. my($got, $rv) = Net::SSLeay::read_ex($ssl, $max); # $ssl - value corresponding to openssl's SSL structure # $max - [optional] max bytes to read (integer) - default is 32768 # # returns a list: two-item list consisting of data read (undef on error), # and return code from SSL_read_ex(). Check openssl doc L =item * renegotiate Turn on flags for renegotiation so that renegotiation will happen my $rv = Net::SSLeay::renegotiate($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 1 on success, 0 on failure =item * rstate_string Returns a 2 letter string indicating the current read state of the SSL object $ssl. my $rv = Net::SSLeay::rstate_string($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 2-letter string Check openssl doc L =item * rstate_string_long Returns a string indicating the current read state of the SSL object ssl. my $rv = Net::SSLeay::rstate_string_long($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: string with current state Check openssl doc L =item * session_reused Query whether a reused session was negotiated during handshake. my $rv = Net::SSLeay::session_reused($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 0 - new session was negotiated; 1 - session was reused. Check openssl doc L =item * set1_param Applies X509 verification parameters $vpm on $ssl my $rv = Net::SSLeay::set1_param($ssl, $vpm); # $ssl - value corresponding to openssl's SSL structure # $vpm - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: 1 on success, 0 on failure =item * set_accept_state Sets $ssl to work in server mode. Net::SSLeay::set_accept_state($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: no return value Check openssl doc L =item * set_bio Connects the BIOs $rbio and $wbio for the read and write operations of the TLS/SSL (encrypted) side of $ssl. Net::SSLeay::set_bio($ssl, $rbio, $wbio); # $ssl - value corresponding to openssl's SSL structure # $rbio - value corresponding to openssl's BIO structure # $wbio - value corresponding to openssl's BIO structure # # returns: no return value Check openssl doc L =item * set_cipher_list Sets the list of ciphers only for ssl. my $rv = Net::SSLeay::set_cipher_list($ssl, $str); # $ssl - value corresponding to openssl's SSL structure # $str - (string) cipher list e.g. '3DES:+RSA' # # returns: 1 if any cipher could be selected and 0 on complete failure Check openssl doc L =item * set_ciphersuites B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Configure the available TLSv1.3 ciphersuites. my $rv = Net::SSLeay::set_ciphersuites($ssl, $str); # $ssl - value corresponding to openssl's SSL structure # $str - colon (":") separated list of TLSv1.3 ciphersuite names in order of preference # # returns: (integer) 1 if the requested ciphersuite list was configured, and 0 otherwise Check openssl doc L =item * set_client_CA_list Sets the list of CAs sent to the client when requesting a client certificate for the chosen $ssl, overriding the setting valid for $ssl's SSL_CTX object. my $rv = Net::SSLeay::set_client_CA_list($ssl, $list); # $ssl - value corresponding to openssl's SSL structure # $list - value corresponding to openssl's STACK_OF(X509_NAME) structure # # returns: no return value Check openssl doc L =item * set_connect_state Sets $ssl to work in client mode. Net::SSLeay::set_connect_state($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: no return value Check openssl doc L =item * set_fd Sets the file descriptor $fd as the input/output facility for the TLS/SSL (encrypted) side of $ssl, $fd will typically be the socket file descriptor of a network connection. my $rv = Net::SSLeay::set_fd($ssl, $fd); # $ssl - value corresponding to openssl's SSL structure # $fd - (integer) file handle (got via perl's fileno) # # returns: 1 on success, 0 on failure Check openssl doc L =item * set_psk_client_callback Sets the psk client callback. Net::SSLeay::set_psk_client_callback($ssl, sub { my $hint = shift; return ($identity, $key) } ); # $ssl - value corresponding to openssl's SSL structure # $hint - PSK identity hint send by the server # $identity - PSK identity # $key - PSK key, hex string without the leading '0x', e.g. 'deadbeef' # # returns: no return value Check openssl doc L =item * set_rfd Sets the file descriptor $fd as the input (read) facility for the TLS/SSL (encrypted) side of $ssl. my $rv = Net::SSLeay::set_rfd($ssl, $fd); # $ssl - value corresponding to openssl's SSL structure # $fd - (integer) file handle (got via perl's fileno) # # returns: 1 on success, 0 on failure Check openssl doc L =item * set_wfd my $rv = Net::SSLeay::set_wfd($ssl, $fd); # $ssl - value corresponding to openssl's SSL structure # $fd - (integer) file handle (got via perl's fileno) # # returns: 1 on success, 0 on failure Check openssl doc L =item * set_info_callback Sets the callback function, that can be used to obtain state information for $ssl during connection setup and use. When callback is undef, the callback setting currently valid for ctx is used. Net::SSLeay::set_info_callback($ssl, $cb, [$data]); # $ssl - value corresponding to openssl's SSL structure # $cb - sub { my ($ssl,$where,$ret,$data) = @_; ... } # # returns: no return value Check openssl doc L =item * CTX_set_info_callback Sets the callback function on ctx, that can be used to obtain state information during ssl connection setup and use. When callback is undef, an existing callback will be disabled. Net::SSLeay::CTX_set_info_callback($ssl, $cb, [$data]); # $ssl - value corresponding to openssl's SSL structure # $cb - sub { my ($ssl,$where,$ret,$data) = @_; ... } # # returns: no return value Check openssl doc L =item * set_pref_cipher Sets the list of available ciphers for $ssl using the control string $str. my $rv = Net::SSLeay::set_pref_cipher($ssl, $str); # $ssl - value corresponding to openssl's SSL structure # $str - (string) cipher list e.g. '3DES:+RSA' # # returns: 1 if any cipher could be selected and 0 on complete failure Check openssl doc L =item * CTX_set_psk_client_callback Sets the psk client callback. Net::SSLeay::CTX_set_psk_client_callback($ssl, sub { my $hint = shift; return ($identity, $key) } ); # $ssl - value corresponding to openssl's SSL structure # $hint - PSK identity hint send by the server # $identity - PSK identity # $key - PSK key, hex string without the leading '0x', e.g. 'deadbeef' # # returns: no return value Check openssl doc L =item * set_purpose my $rv = Net::SSLeay::set_purpose($ssl, $purpose); # $ssl - value corresponding to openssl's SSL structure # $purpose - (integer) purpose identifier # # returns: 1 on success, 0 on failure For more info about available $purpose identifiers see L. =item * set_quiet_shutdown Sets the 'quiet shutdown' flag for $ssl to be $mode. Net::SSLeay::set_quiet_shutdown($ssl, $mode); # $ssl - value corresponding to openssl's SSL structure # $mode - 0 or 1 # # returns: no return value Check openssl doc L =item * set_session Set a TLS/SSL session to be used during TLS/SSL connect. my $rv = Net::SSLeay::set_session($to, $ses); # $to - value corresponding to openssl's SSL structure # $ses - value corresponding to openssl's SSL_SESSION structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * set_session_id_context Sets the context $sid_ctx of length $sid_ctx_len within which a session can be reused for the $ssl object. my $rv = Net::SSLeay::set_session_id_context($ssl, $sid_ctx, $sid_ctx_len); # $ssl - value corresponding to openssl's SSL structure # $sid_ctx - data buffer # $sid_ctx_len - length of data in $sid_ctx # # returns: 1 on success, 0 on failure Check openssl doc L =item * set_session_secret_cb Setup pre-shared secret session resumption function. Net::SSLeay::set_session_secret_cb($ssl, $func, $data); # $ssl - value corresponding to openssl's SSL structure # $func - perl reference to callback function # $data - [optional] data that will be passed to callback function when invoked # # returns: no return value The callback function will be called like: callback_function($secret, $ciphers, $pref_cipher, $data); # $secret is the current master session key, usually all 0s at the beginning of a session # $ciphers is ref to an array of peer cipher names # $pref_cipher is a ref to an index into the list of cipher names of # the preferred cipher. Set it if you want to specify a preferred cipher # $data is the data passed to set_session_secret_cb The callback function should return 1 if it likes the suggested cipher (or has selected an alternative by setting pref_cipher), else it should return 0 (in which case OpenSSL will select its own preferred cipher). With OpenSSL 1.1 and later, callback_function can change the master key for the session by altering $secret and returning 1. =item * CTX_set_tlsext_ticket_getkey_cb Setup encryption for TLS session tickets (stateless session reuse). Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb($ctx, $func, $data); # $ctx - value corresponding to openssl's SSL_CTX structure # $func - perl reference to callback function # $data - [optional] data that will be passed to callback function when invoked # # returns: no return value The callback function will be called like: getkey($data,[$key_name]) -> ($key,$current_key_name) # $data is the data passed to set_session_secret_cb # $key_name is the name of the key OpenSSL has extracted from the session ticket # $key is the requested key for ticket encryption + HMAC # $current_key_name is the name for the currently valid key OpenSSL will call the function without a key name if it generates a new ticket. It then needs the callback to return the encryption+HMAC key and an identifier (key name) for this key. When OpenSSL gets a session ticket from the client it extracts the key name and calls the callback with this name as argument. It then expects the callback to return the encryption+HMAC key matching the requested key name and and also the key name which should be used at the moment. If the requested key name and the returned key name differ it means that this session ticket was created with an expired key and need to be renewed. In this case OpenSSL will call the callback again with no key name to create a new session ticket based on the old one. The key must be at least 32 byte of random data which can be created with RAND_bytes. Internally the first 16 byte are used as key in AES-128 encryption while the next 16 byte are used for the SHA-256 HMAC. The key name are binary data and must be exactly 16 byte long. Example: Net::SSLeay::RAND_bytes(my $oldkey,32); Net::SSLeay::RAND_bytes(my $newkey,32); my $oldkey_name = pack("a16",'oldsecret'); my $newkey_name = pack("a16",'newsecret'); my @keys = ( [ $newkey_name, $newkey ], # current active key [ $oldkey_name, $oldkey ], # already expired ); Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb($server2->_ctx, sub { my ($mykeys,$name) = @_; # return (current_key, current_key_name) if no name given return ($mykeys->[0][1],$mykeys->[0][0]) if ! $name; # return (matching_key, current_key_name) if we find a key matching # the given name for(my $i = 0; $i<@$mykeys; $i++) { next if $name ne $mykeys->[$i][0]; return ($mykeys->[$i][1],$mykeys->[0][0]); } # no matching key found return; },\@keys); This function is based on the OpenSSL function SSL_CTX_set_tlsext_ticket_key_cb but provides a simpler to use interface. For more information see L =item * set_session_ticket_ext_cb Setup callback for TLS session tickets (stateless session reuse). Net::SSLeay::set_session_ticket_ext_cb($ssl, $func, $data); # $ssl - value corresponding to openssl's SSL structure # $func - perl reference to callback function # $data - [optional] data that will be passed to callback function when invoked # # returns: no return value The callback function will be called like: getticket($ssl,$ticket,$data) -> $return_value # $ssl is a value corresponding to openssl's SSL structure # $ticket is a value of received TLS session ticket (can also be empty) # $data is the data passed to set_session_ticket_ext_cb # $return_value is either 0 (failure) or 1 (success) This function is based on the OpenSSL function SSL_set_session_ticket_ext_cb. =item * set_session_ticket_ext Set TLS session ticket (stateless session reuse). Net::SSLeay::set_session_ticket_ext($ssl, $ticket); # $ssl - value corresponding to openssl's SSL structure # $ticket - is a value of TLS session ticket which client will send (can also be empty string) # # returns: no return value The callback function will be called like: getticket($ssl,$ticket,$data) -> $return_value # $ssl is a value corresponding to openssl's SSL structure # $ticket is a value of received TLS session ticket (can also be empty) # $data is the data passed to set_session_ticket_ext_cb # $return_value is either 0 (failure) or 1 (success) This function is based on the OpenSSL function SSL_set_session_ticket_ext_cb. =item * set_shutdown Sets the shutdown state of $ssl to $mode. Net::SSLeay::set_shutdown($ssl, $mode); # $ssl - value corresponding to openssl's SSL structure # $mode - (integer) shutdown mode: # 0 - No shutdown # 1 - SSL_SENT_SHUTDOWN # 2 - SSL_RECEIVED_SHUTDOWN # 3 - SSL_RECEIVED_SHUTDOWN+SSL_SENT_SHUTDOWN # # returns: no return value Check openssl doc L =item * set_ssl_method Sets a new TLS/SSL method for a particular $ssl object. my $rv = Net::SSLeay::set_ssl_method($ssl, $method); # $ssl - value corresponding to openssl's SSL structure # $method - value corresponding to openssl's SSL_METHOD structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * set_tmp_dh Sets DH parameters to be used to be $dh. my $rv = Net::SSLeay::set_tmp_dh($ssl, $dh); # $ssl - value corresponding to openssl's SSL structure # $dh - value corresponding to openssl's DH structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * set_tmp_dh_callback Sets the callback function for $ssl to be used when a DH parameters are required to $dh_cb. ??? (does this function really work?) Net::SSLeay::set_tmp_dh_callback($ssl, $dh); # $ssl - value corresponding to openssl's SSL structure # $dh_cb - pointer to function ??? # # returns: no return value Check openssl doc L =item * set_tmp_rsa Sets the temporary/ephemeral RSA key to be used in $ssl to be $rsa. my $rv = Net::SSLeay::set_tmp_rsa($ssl, $rsa); # $ssl - value corresponding to openssl's SSL structure # $rsa - value corresponding to openssl's RSA structure # # returns: 1 on success, 0 on failure Example: $rsakey = Net::SSLeay::RSA_generate_key(); Net::SSLeay::set_tmp_rsa($ssl, $rsakey); Net::SSLeay::RSA_free($rsakey); Check openssl doc L =item * set_tmp_rsa_callback Sets the callback function for $ssl to be used when a temporary/ephemeral RSA key is required to $tmp_rsa_callback. ??? (does this function really work?) Net::SSLeay::set_tmp_rsa_callback($ssl, $tmp_rsa_callback); # $ssl - value corresponding to openssl's SSL structure # $tmp_rsa_callback - (function pointer) ??? # # returns: no return value Check openssl doc L =item * set_trust my $rv = Net::SSLeay::set_trust($ssl, $trust); # $ssl - value corresponding to openssl's SSL structure # $trust - (integer) trust identifier # # returns: the original value For more details about $trust values see L. =item * shutdown Shuts down an active TLS/SSL connection. It sends the 'close notify' shutdown alert to the peer. my $rv = Net::SSLeay::shutdown($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 1 - shutdown was successfully completed # 0 - shutdown is not yet finished, # -1 - shutdown was not successful Check openssl doc L =item * state_string Returns a 6 letter string indicating the current state of the SSL object $ssl. my $rv = Net::SSLeay::state_string($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: 6-letter string Check openssl doc L =item * state_string_long Returns a string indicating the current state of the SSL object $ssl. my $rv = Net::SSLeay::state_string_long($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: state strings Check openssl doc L =item * set_default_passwd_cb B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0f. Not needed with LibreSSL. Sets the default password callback called when loading/storing a PEM certificate with encryption for $ssl. Net::SSLeay::set_default_passwd_cb($ssl, $func); # $ssl - value corresponding to openssl's SSL structure # $func - perl reference to callback function # # returns: no return value Check openssl doc L =item * set_default_passwd_cb_userdata B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0f. Not needed with LibreSSL. Sets a pointer to userdata which will be provided to the password callback of $ssl on invocation. Net::SSLeay::set_default_passwd_cb_userdata($ssl, $userdata); # $ssl - value corresponding to openssl's SSL structure # $userdata - data that will be passed to callback function when invoked # # returns: no return value Check openssl doc L =item * use_PrivateKey Adds $pkey as private key to $ssl. my $rv = Net::SSLeay::use_PrivateKey($ssl, $pkey); # $ssl - value corresponding to openssl's SSL structure # $pkey - value corresponding to openssl's EVP_PKEY structure # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * use_PrivateKey_ASN1 Adds the private key of type $pk stored in $data to $ssl. my $rv = Net::SSLeay::use_PrivateKey_ASN1($pk, $ssl, $d, $len); # $pk - (integer) key type, NID of corresponding algorithm # $ssl - value corresponding to openssl's SSL structure # $data - key data (binary) # $len - length of $data # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * use_PrivateKey_file Adds the first private key found in $file to $ssl. my $rv = Net::SSLeay::use_PrivateKey_file($ssl, $file, $type); # $ssl - value corresponding to openssl's SSL structure # $file - (string) file name # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * use_RSAPrivateKey Adds $rsa as RSA private key to $ssl. my $rv = Net::SSLeay::use_RSAPrivateKey($ssl, $rsa); # $ssl - value corresponding to openssl's SSL structure # $rsa - value corresponding to openssl's RSA structure # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * use_RSAPrivateKey_ASN1 Adds RSA private key stored in $data to $ssl. my $rv = Net::SSLeay::use_RSAPrivateKey_ASN1($ssl, $data, $len); # $ssl - value corresponding to openssl's SSL structure # $data - key data (binary) # $len - length of $data # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * use_RSAPrivateKey_file Adds the first RSA private key found in $file to $ssl. my $rv = Net::SSLeay::use_RSAPrivateKey_file($ssl, $file, $type); # $ssl - value corresponding to openssl's SSL structure # $file - (string) file name # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * use_certificate Loads the certificate $x into $ssl. my $rv = Net::SSLeay::use_certificate($ssl, $x); # $ssl - value corresponding to openssl's SSL structure # $x - value corresponding to openssl's X509 structure # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * use_certificate_ASN1 Loads the ASN1 encoded certificate from $data to $ssl. my $rv = Net::SSLeay::use_certificate_ASN1($ssl, $data, $len); # $ssl - value corresponding to openssl's SSL structure # $data - certificate data (binary) # $len - length of $data # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * use_certificate_chain_file B: not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0 Loads a certificate chain from $file into $ssl. The certificates must be in PEM format and must be sorted starting with the subject's certificate (actual client or server certificate), followed by intermediate CA certificates if applicable, and ending at the highest level (root) CA. my $rv = Net::SSLeay::use_certificate_chain_file($ssl, $file); # $ssl - value corresponding to openssl's SSL structure # $file - (string) file name # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * use_certificate_file Loads the first certificate stored in $file into $ssl. my $rv = Net::SSLeay::use_certificate_file($ssl, $file, $type); # $ssl - value corresponding to openssl's SSL structure # $file - (string) file name # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 # # returns: 1 on success, otherwise check out the error stack to find out the reason Check openssl doc L =item * get_version Returns SSL/TLS protocol name my $rv = Net::SSLeay::get_version($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (string) protocol name, see OpenSSL manual for the full list # TLSv1 # TLSv1.3 Check openssl doc L =item * version Returns SSL/TLS protocol version my $rv = Net::SSLeay::version($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) protocol version, see OpenSSL manual for the full list # 0x0301 - TLS1_VERSION (TLSv1) # 0xFEFF - DTLS1_VERSION (DTLSv1) Check openssl doc L =item * client_version B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL Returns TLS protocol version used by the client when initiating the connection my $rv = Net::SSLeay::client_version($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) protocol version, see OpenSSL manual for the full list # 0x0301 - TLS1_VERSION (TLSv1) # 0xFEFF - DTLS1_VERSION (DTLSv1) Check openssl doc L =item * is_dtls B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL my $rv = Net::SSLeay::is_dtls($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) zero or one # 0 - connection is not using DTLS # 1 - connection is using DTLS Check openssl doc L =item * want Returns state information for the SSL object $ssl. my $rv = Net::SSLeay::want($ssl); # $ssl - value corresponding to openssl's SSL structure # # returns: state # 1 - SSL_NOTHING # 2 - SSL_WRITING # 3 - SSL_READING # 4 - SSL_X509_LOOKUP Check openssl doc L =item * write Writes data from the buffer $data into the specified $ssl connection. my $rv = Net::SSLeay::write($ssl, $data); # $ssl - value corresponding to openssl's SSL structure # $data - data to be written # # returns: >0 - (success) number of bytes actually written to the TLS/SSL connection # 0 - write not successful, probably the underlying connection was closed # <0 - error Check openssl doc L =item * write_ex B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Writes data from the buffer $data into the specified $ssl connection. my ($len, $rv) = Net::SSLeay::write_ex($ssl, $data); # $ssl - value corresponding to openssl's SSL structure # $data - data to be written # # returns a list: two-item list consisting of number of bytes written, # and return code from SSL_write_ex() Check openssl doc L =item * write_partial B Does not exactly correspond to any low level API function Writes a fragment of data in $data from the buffer $data into the specified $ssl connection. This is a non-blocking function like L. my $rv = Net::SSLeay::write_partial($ssl, $from, $count, $data); # $ssl - value corresponding to openssl's SSL structure # $from - (integer) offset from the beginning of $data # $count - (integer) length of data to be written # $data - data buffer # # returns: >0 - (success) number of bytes actually written to the TLS/SSL connection # 0 - write not successful, probably the underlying connection was closed # <0 - error =item * set_tlsext_host_name B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.8f Sets TLS servername extension on SLL object $ssl to value $name. my $rv = set_tlsext_host_name($ssl, $name); # $ssl - value corresponding to openssl's SSL structure # $name - (string) name to be set # # returns: 1 on success, 0 on failure =back =head3 Low level API: RAND_* related functions Check openssl doc related to RAND stuff L =over =item * RAND_add Mixes the $num bytes at $buf into the PRNG state. Net::SSLeay::RAND_add($buf, $num, $entropy); # $buf - buffer with data to be mixed into the PRNG state # $num - number of bytes in $buf # $entropy - estimate of how much randomness is contained in $buf (in bytes) # # returns: no return value Check openssl doc L =item * RAND_seed Equivalent to L when $num == $entropy. Net::SSLeay::RAND_seed($buf); # Perlishly figures out buf size # $buf - buffer with data to be mixed into the PRNG state # $num - number of bytes in $buf # # returns: no return value Check openssl doc L =item * RAND_status Gives PRNG status (seeded enough or not). my $rv = Net::SSLeay::RAND_status(); #returns: 1 if the PRNG has been seeded with enough data, 0 otherwise Check openssl doc L =item * RAND_bytes Puts $num cryptographically strong pseudo-random bytes into $buf. my $rv = Net::SSLeay::RAND_bytes($buf, $num); # $buf - buffer where the random data will be stored # $num - the size (in bytes) of requested random data # # returns: 1 on success, -1 if not supported by the current RAND method, or 0 on other failure Check openssl doc L =item * RAND_priv_bytes B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL Puts $num cryptographically strong pseudo-random bytes into $buf. my $rv = Net::SSLeay::RAND_priv_bytes($buf, $num); # $buf - buffer where the random data will be stored # $num - the size (in bytes) of requested random data # # returns: 1 on success, -1 if not supported by the current RAND method, or 0 on other failure RAND_priv_bytes has the same semantics as RAND_bytes, but see see the documentation for more information. Check openssl doc L =item * RAND_pseudo_bytes Puts $num pseudo-random (not necessarily unpredictable) bytes into $buf. my $rv = Net::SSLeay::RAND_pseudo_bytes($buf, $num); # $buf - buffer where the random data will be stored # $num - the size (in bytes) of requested random data # # returns: 1 if the bytes generated are cryptographically strong, 0 otherwise Check openssl doc L =item * RAND_cleanup Erase the PRNG state. Net::SSLeay::RAND_cleanup(); # no args, no return value Check openssl doc L =item * RAND_egd_bytes Queries the entropy gathering daemon EGD on socket $path for $bytes bytes. my $rv = Net::SSLeay::RAND_egd_bytes($path, $bytes); # $path - path to a socket of entropy gathering daemon EGD # $bytes - number of bytes we want from EGD # # returns: the number of bytes read from the daemon on success, and -1 on failure Check openssl doc L =item * RAND_file_name Generates a default path for the random seed file. my $file = Net::SSLeay::RAND_file_name($num); # $num - maximum size of returned file name # # returns: string with file name on success, '' (empty string) on failure Check openssl doc L =item * RAND_load_file B Is no longer functional on LibreSSL Reads $max_bytes of bytes from $file_name and adds them to the PRNG. my $rv = Net::SSLeay::RAND_load_file($file_name, $max_bytes); # $file_name - the name of file # $max_bytes - bytes to read from $file_name; -1 => the complete file is read # # returns: the number of bytes read Check openssl doc L =item * RAND_write_file Writes 1024 random bytes to $file_name which can be used to initialize the PRNG by calling L in a later session. my $rv = Net::SSLeay::RAND_write_file($file_name); # $file_name - the name of file # # returns: the number of bytes written, and -1 if the bytes written were generated without appropriate seed Check openssl doc L =item * RAND_poll Collects some entropy from operating system and adds it to the PRNG. my $rv = Net::SSLeay::RAND_poll(); # returns: 1 on success, 0 on failure (unable to gather reasonable entropy) =back =head3 Low level API: OBJ_* related functions =over =item * OBJ_cmp Compares ASN1_OBJECT $a to ASN1_OBJECT $b. my $rv = Net::SSLeay::OBJ_cmp($a, $b); # $a - value corresponding to openssl's ASN1_OBJECT structure # $b - value corresponding to openssl's ASN1_OBJECT structure # # returns: if the two are identical 0 is returned Check openssl doc L =item * OBJ_dup Returns a copy/duplicate of $o. my $rv = Net::SSLeay::OBJ_dup($o); # $o - value corresponding to openssl's ASN1_OBJECT structure # # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) Check openssl doc L =item * OBJ_nid2ln Returns long name for given NID $n. my $rv = Net::SSLeay::OBJ_nid2ln($n); # $n - (integer) NID # # returns: (string) long name e.g. 'commonName' Check openssl doc L =item * OBJ_ln2nid Returns NID corresponding to given long name $n. my $rv = Net::SSLeay::OBJ_ln2nid($s); # $s - (string) long name e.g. 'commonName' # # returns: (integer) NID =item * OBJ_nid2sn Returns short name for given NID $n. my $rv = Net::SSLeay::OBJ_nid2sn($n); # $n - (integer) NID # # returns: (string) short name e.g. 'CN' Example: print Net::SSLeay::OBJ_nid2sn(&Net::SSLeay::NID_commonName); =item * OBJ_sn2nid Returns NID corresponding to given short name $s. my $rv = Net::SSLeay::OBJ_sn2nid($s); # $s - (string) short name e.g. 'CN' # # returns: (integer) NID Example: print "NID_commonName constant=", &Net::SSLeay::NID_commonName; print "OBJ_sn2nid('CN')=", Net::SSLeay::OBJ_sn2nid('CN'); =item * OBJ_nid2obj Returns ASN1_OBJECT for given NID $n. my $rv = Net::SSLeay::OBJ_nid2obj($n); # $n - (integer) NID # # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) Check openssl doc L =item * OBJ_obj2nid Returns NID corresponding to given ASN1_OBJECT $o. my $rv = Net::SSLeay::OBJ_obj2nid($o); # $o - value corresponding to openssl's ASN1_OBJECT structure # # returns: (integer) NID Check openssl doc L =item * OBJ_txt2obj Converts the text string s into an ASN1_OBJECT structure. If $no_name is 0 then long names (e.g. 'commonName') and short names (e.g. 'CN') will be interpreted as well as numerical forms (e.g. '2.5.4.3'). If $no_name is 1 only the numerical form is acceptable. my $rv = Net::SSLeay::OBJ_txt2obj($s, $no_name); # $s - text string to be converted # $no_name - (integer) 0 or 1 # # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) Check openssl doc L =item * OBJ_obj2txt Converts the ASN1_OBJECT a into a textual representation. Net::SSLeay::OBJ_obj2txt($a, $no_name); # $a - value corresponding to openssl's ASN1_OBJECT structure # $no_name - (integer) 0 or 1 # # returns: textual representation e.g. 'commonName' ($no_name=0), '2.5.4.3' ($no_name=1) Check openssl doc L =item * OBJ_txt2nid Returns NID corresponding to text string $s which can be a long name, a short name or the numerical representation of an object. my $rv = Net::SSLeay::OBJ_txt2nid($s); # $s - (string) e.g. 'commonName' or 'CN' or '2.5.4.3' # # returns: (integer) NID Example: my $nid = Net::SSLeay::OBJ_txt2nid('2.5.4.3'); Net::SSLeay::OBJ_nid2sn($n); Check openssl doc L =back =head3 Low level API: ASN1_INTEGER_* related functions =over =item * ASN1_INTEGER_new B not available in Net-SSLeay-1.45 and before Creates a new ASN1_INTEGER structure. my $rv = Net::SSLeay::ASN1_INTEGER_new(); # # returns: value corresponding to openssl's ASN1_INTEGER structure (0 on failure) =item * ASN1_INTEGER_free B not available in Net-SSLeay-1.45 and before Free an allocated ASN1_INTEGER structure. Net::SSLeay::ASN1_INTEGER_free($i); # $i - value corresponding to openssl's ASN1_INTEGER structure # # returns: no return value =item * ASN1_INTEGER_get B not available in Net-SSLeay-1.45 and before Returns integer value of given ASN1_INTEGER object. B If the value stored in ASN1_INTEGER is greater than max. integer that can be stored in 'long' type (usually 32bit but may vary according to platform) then this function will return -1. For getting large ASN1_INTEGER values consider using L or L. my $rv = Net::SSLeay::ASN1_INTEGER_get($a); # $a - value corresponding to openssl's ASN1_INTEGER structure # # returns: integer value of ASN1_INTEGER object in $a =item * ASN1_INTEGER_set B not available in Net-SSLeay-1.45 and before Sets value of given ASN1_INTEGER object to value $val B $val has max. limit (= max. integer that can be stored in 'long' type). For setting large ASN1_INTEGER values consider using L or L. my $rv = Net::SSLeay::ASN1_INTEGER_set($i, $val); # $i - value corresponding to openssl's ASN1_INTEGER structure # $val - integer value # # returns: 1 on success, 0 on failure =item * P_ASN1_INTEGER_get_dec B not available in Net-SSLeay-1.45 and before Returns string with decimal representation of integer value of given ASN1_INTEGER object. Net::SSLeay::P_ASN1_INTEGER_get_dec($i); # $i - value corresponding to openssl's ASN1_INTEGER structure # # returns: string with decimal representation =item * P_ASN1_INTEGER_get_hex B not available in Net-SSLeay-1.45 and before Returns string with hexadecimal representation of integer value of given ASN1_INTEGER object. Net::SSLeay::P_ASN1_INTEGER_get_hex($i); # $i - value corresponding to openssl's ASN1_INTEGER structure # # returns: string with hexadecimal representation =item * P_ASN1_INTEGER_set_dec B not available in Net-SSLeay-1.45 and before Sets value of given ASN1_INTEGER object to value $val (decimal string, suitable for large integers) Net::SSLeay::P_ASN1_INTEGER_set_dec($i, $str); # $i - value corresponding to openssl's ASN1_INTEGER structure # $str - string with decimal representation # # returns: 1 on success, 0 on failure =item * P_ASN1_INTEGER_set_hex B not available in Net-SSLeay-1.45 and before Sets value of given ASN1_INTEGER object to value $val (hexadecimal string, suitable for large integers) Net::SSLeay::P_ASN1_INTEGER_set_hex($i, $str); # $i - value corresponding to openssl's ASN1_INTEGER structure # $str - string with hexadecimal representation # # returns: 1 on success, 0 on failure =back =head3 Low level API: ASN1_STRING_* related functions =over =item * P_ASN1_STRING_get B not available in Net-SSLeay-1.45 and before Returns string value of given ASN1_STRING object. Net::SSLeay::P_ASN1_STRING_get($s, $utf8_decode); # $s - value corresponding to openssl's ASN1_STRING structure # $utf8_decode - [optional] 0 or 1 whether the returned value should be utf8 decoded (default=0) # # returns: string $string = Net::SSLeay::P_ASN1_STRING_get($s); #is the same as: $string = Net::SSLeay::P_ASN1_STRING_get($s, 0); =back =head3 Low level API: ASN1_TIME_* related functions =over =item * ASN1_TIME_new B not available in Net-SSLeay-1.42 and before my $time = ASN1_TIME_new(); # returns: value corresponding to openssl's ASN1_TIME structure =item * ASN1_TIME_free B not available in Net-SSLeay-1.42 and before ASN1_TIME_free($time); # $time - value corresponding to openssl's ASN1_TIME structure =item * ASN1_TIME_set B not available in Net-SSLeay-1.42 and before ASN1_TIME_set($time, $t); # $time - value corresponding to openssl's ASN1_TIME structure # $t - time value in seconds since 1.1.1970 B It is platform dependent how this function will handle dates after 2038. Although perl's integer is large enough the internal implementation of this function is dependent on the size of time_t structure (32bit time_t has problem with 2038). If you want to safely set date and time after 2038 use function L. =item * P_ASN1_TIME_get_isotime B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7e B Does not exactly correspond to any low level API function Gives ISO-8601 string representation of ASN1_TIME structure. my $datetime_string = P_ASN1_TIME_get_isotime($time); # $time - value corresponding to openssl's ASN1_TIME structure # # returns: datetime string like '2033-05-16T20:39:37Z' or '' on failure The output format is compatible with module L =item * P_ASN1_TIME_set_isotime B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7e B Does not exactly correspond to any low level API function Sets time and date value of ANS1_time structure. my $rv = P_ASN1_TIME_set_isotime($time, $string); # $time - value corresponding to openssl's ASN1_TIME structure # $string - ISO-8601 timedate string like '2033-05-16T20:39:37Z' # # returns: 1 on success, 0 on failure The C<$string> parameter has to be in full form like C<"2012-03-22T23:55:33"> or C<"2012-03-22T23:55:33Z"> or C<"2012-03-22T23:55:33CET">. Short forms like C<"2012-03-22T23:55"> or C<"2012-03-22"> are not supported. =item * P_ASN1_TIME_put2string B not available in Net-SSLeay-1.42 and before, has bugs with openssl-0.9.8i B Does not exactly correspond to any low level API function Gives string representation of ASN1_TIME structure. my $str = P_ASN1_TIME_put2string($time); # $time - value corresponding to openssl's ASN1_TIME structure # # returns: datetime string like 'May 16 20:39:37 2033 GMT' =item * P_ASN1_UTCTIME_put2string B deprecated function, only for backward compatibility, just an alias for L =back =head3 Low level API: X509_* related functions =over =item * X509_new B not available in Net-SSLeay-1.45 and before Allocates and initializes a X509 structure. my $rv = Net::SSLeay::X509_new(); # # returns: value corresponding to openssl's X509 structure (0 on failure) Check openssl doc L =item * X509_free Frees up the X509 structure. Net::SSLeay::X509_free($a); # $a - value corresponding to openssl's X509 structure # # returns: no return value Check openssl doc L =item * X509_check_host B not available in Net-SSLeay-1.68 and before; requires at least OpenSSL 1.0.2. X509_CHECK_FLAG_NEVER_CHECK_SUBJECT requires OpenSSL 1.1.0. Checks f the certificate Subject Alternative Name (SAN) or Subject CommonName (CN) matches the specified host name. my $rv = Net::SSLeay::X509_check_host($cert, $name, $flags, $peername); # $cert - value corresponding to openssl's X509 structure # $name - host name to check # $flags (optional, default: 0) - can be the bitwise OR of: # &Net::SSLeay::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT # &Net::SSLeay::X509_CHECK_FLAG_NO_WILDCARDS # &Net::SSLeay::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS # &Net::SSLeay::X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS # &Net::SSLeay::X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS # &Net::SSLeay::X509_CHECK_FLAG_NEVER_CHECK_SUBJECT # $peername (optional) - If not omitted and $host matches $cert, # a copy of the matching SAN or CN from # the peer certificate is stored in $peername. # # returns: # 1 for a successful match # 0 for a failed match # -1 for an internal error # -2 if the input is malformed Check openssl doc L. =item * X509_check_email B not available in Net-SSLeay-1.68 and before; requires at least OpenSSL 1.0.2. Checks if the certificate matches the specified email address. my $rv = Net::SSLeay::X509_check_email($cert, $address, $flags); # $cert - value corresponding to openssl's X509 structure # $address - email address to check # $flags (optional, default: 0) - see X509_check_host() # # returns: see X509_check_host() Check openssl doc L. =item * X509_check_ip B not available in Net-SSLeay-1.68 and before; requires at least OpenSSL 1.0.2. Checks if the certificate matches the specified IPv4 or IPv6 address. my $rv = Net::SSLeay::X509_check_email($cert, $address, $flags); # $cert - value corresponding to openssl's X509 structure # $address - IP address to check in binary format, in network byte order # $flags (optional, default: 0) - see X509_check_host() # # returns: see X509_check_host() Check openssl doc L. =item * X509_check_ip_asc B not available in Net-SSLeay-1.68 and before; requires at least OpenSSL 1.0.2. Checks if the certificate matches the specified IPv4 or IPv6 address. my $rv = Net::SSLeay::X509_check_email($cert, $address, $flags); # $cert - value corresponding to openssl's X509 structure # $address - IP address to check in text representation # $flags (optional, default: 0) - see X509_check_host() # # returns: see X509_check_host() Check openssl doc L. =item * X509_certificate_type B not available in Net-SSLeay-1.45 and before Returns bitmask with type of certificate $x. my $rv = Net::SSLeay::X509_certificate_type($x); # $x - value corresponding to openssl's X509 structure # # returns: (integer) bitmask with certificate type #to decode bitmask returned by this function use these constants: &Net::SSLeay::EVP_PKS_DSA &Net::SSLeay::EVP_PKS_EC &Net::SSLeay::EVP_PKS_RSA &Net::SSLeay::EVP_PKT_ENC &Net::SSLeay::EVP_PKT_EXCH &Net::SSLeay::EVP_PKT_EXP &Net::SSLeay::EVP_PKT_SIGN &Net::SSLeay::EVP_PK_DH &Net::SSLeay::EVP_PK_DSA &Net::SSLeay::EVP_PK_EC &Net::SSLeay::EVP_PK_RSA =item * X509_digest B not available in Net-SSLeay-1.45 and before Computes digest/fingerprint of X509 $data using $type hash function. my $digest_value = Net::SSLeay::X509_digest($data, $type); # $data - value corresponding to openssl's X509 structure # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() # # returns: hash value (binary) #to get printable (hex) value of digest use: print unpack('H*', $digest_value); =item * X509_issuer_and_serial_hash B not available in Net-SSLeay-1.45 and before Sort of a checksum of issuer name and serial number of X509 certificate $x. The result is not a full hash (e.g. sha-1), it is kind-of-a-hash truncated to the size of 'unsigned long' (32 bits). The resulting value might differ across different openssl versions for the same X509 certificate. my $rv = Net::SSLeay::X509_issuer_and_serial_hash($x); # $x - value corresponding to openssl's X509 structure # # returns: number representing checksum =item * X509_issuer_name_hash B not available in Net-SSLeay-1.45 and before Sort of a checksum of issuer name of X509 certificate $x. The result is not a full hash (e.g. sha-1), it is kind-of-a-hash truncated to the size of 'unsigned long' (32 bits). The resulting value might differ across different openssl versions for the same X509 certificate. my $rv = Net::SSLeay::X509_issuer_name_hash($x); # $x - value corresponding to openssl's X509 structure # # returns: number representing checksum =item * X509_subject_name_hash B not available in Net-SSLeay-1.45 and before Sort of a checksum of subject name of X509 certificate $x. The result is not a full hash (e.g. sha-1), it is kind-of-a-hash truncated to the size of 'unsigned long' (32 bits). The resulting value might differ across different openssl versions for the same X509 certificate. my $rv = Net::SSLeay::X509_subject_name_hash($x); # $x - value corresponding to openssl's X509 structure # # returns: number representing checksum =item * X509_pubkey_digest B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Computes digest/fingerprint of public key from X509 certificate $data using $type hash function. my $digest_value = Net::SSLeay::X509_pubkey_digest($data, $type); # $data - value corresponding to openssl's X509 structure # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() # # returns: hash value (binary) #to get printable (hex) value of digest use: print unpack('H*', $digest_value); =item * X509_set_issuer_name B not available in Net-SSLeay-1.45 and before Sets issuer of X509 certificate $x to $name. my $rv = Net::SSLeay::X509_set_issuer_name($x, $name); # $x - value corresponding to openssl's X509 structure # $name - value corresponding to openssl's X509_NAME structure # # returns: 1 on success, 0 on failure =item * X509_set_pubkey B not available in Net-SSLeay-1.45 and before Sets public key of X509 certificate $x to $pkey. my $rv = Net::SSLeay::X509_set_pubkey($x, $pkey); # $x - value corresponding to openssl's X509 structure # $pkey - value corresponding to openssl's EVP_PKEY structure # # returns: 1 on success, 0 on failure =item * X509_set_serialNumber B not available in Net-SSLeay-1.45 and before Sets serial number of X509 certificate $x to $serial. my $rv = Net::SSLeay::X509_set_serialNumber($x, $serial); # $x - value corresponding to openssl's X509 structure # $serial - value corresponding to openssl's ASN1_INTEGER structure # # returns: 1 on success, 0 on failure #to create $serial value use one of these: $serial = Net::SSLeay::P_ASN1_INTEGER_set_hex('45ad6f'); $serial = Net::SSLeay::P_ASN1_INTEGER_set_dec('7896541238529631478'); $serial = Net::SSLeay::ASN1_INTEGER_set(45896); =item * X509_set_subject_name B not available in Net-SSLeay-1.45 and before Sets subject of X509 certificate $x to $name. my $rv = Net::SSLeay::X509_set_subject_name($x, $name); # $x - value corresponding to openssl's X509 structure # $name - value corresponding to openssl's X509_NAME structure # # returns: 1 on success, 0 on failure =item * X509_set_version B not available in Net-SSLeay-1.45 and before Set 'version' value for X509 certificate $ to $version. my $rv = Net::SSLeay::X509_set_version($x, $version); # $x - value corresponding to openssl's X509 structure # $version - (integer) version number # # returns: 1 on success, 0 on failure =item * X509_sign B not available in Net-SSLeay-1.45 and before Sign X509 certificate $x with private key $pkey (using digest algorithm $md). my $rv = Net::SSLeay::X509_sign($x, $pkey, $md); # $x - value corresponding to openssl's X509 structure # $pkey - value corresponding to openssl's EVP_PKEY structure # $md - value corresponding to openssl's EVP_MD structure # # returns: 1 on success, 0 on failure =item * X509_verify B not available in Net-SSLeay-1.45 and before Verifies X509 object $a using public key $r (pubkey of issuing CA). my $rv = Net::SSLeay::X509_verify($x, $r); # $x - value corresponding to openssl's X509 structure # $r - value corresponding to openssl's EVP_PKEY structure # # returns: 0 - verify failure, 1 - verify OK, <0 - error =item * X509_get_ext_count B not available in Net-SSLeay-1.45 and before Returns the total number of extensions in X509 object $x. my $rv = Net::SSLeay::X509_get_ext_count($x); # $x - value corresponding to openssl's X509 structure # # returns: count of extensions =item * X509_get_pubkey B not available in Net-SSLeay-1.45 and before Returns public key corresponding to given X509 object $x. my $rv = Net::SSLeay::X509_get_pubkey($x); # $x - value corresponding to openssl's X509 structure # # returns: value corresponding to openssl's EVP_PKEY structure (0 on failure) B This method returns only the public key's key bits, without the algorithm or parameters. Use C to return the full public key (SPKI) instead. =item * X509_get_X509_PUBKEY B not available in Net-SSLeay-1.72 and before Returns the full public key (SPKI) of given X509 certificate $x. Net::SSLeay::X509_get_X509_PUBKEY($x); # $x - value corresponding to openssl's X509 structure # # returns: public key data in DER format (binary) =item * X509_get_serialNumber B not available in Net-SSLeay-1.45 and before Returns serial number of X509 certificate $x. my $rv = Net::SSLeay::X509_get_serialNumber($x); # $x - value corresponding to openssl's X509 structure # # returns: value corresponding to openssl's ASN1_INTEGER structure (0 on failure) See L, L or L to decode ASN1_INTEGER object. =item * X509_get0_serialNumber B available in Net-SSLeay-1.86 onwards X509_get0_serialNumber() is the same as X509_get_serialNumber() except it accepts a const parameter and returns a const result. =item * X509_get_version B not available in Net-SSLeay-1.45 and before Returns 'version' value of given X509 certificate $x. my $rv = Net::SSLeay::X509_get_version($x); # $x - value corresponding to openssl's X509 structure # # returns: (integer) version =item * X509_get_ext Returns X509_EXTENSION from $x509 based on given position/index. my $rv = Net::SSLeay::X509_get_ext($x509, $index); # $x509 - value corresponding to openssl's X509 structure # $index - (integer) position/index of extension within $x509 # # returns: value corresponding to openssl's X509_EXTENSION structure (0 on failure) =item * X509_get_ext_by_NID Returns X509_EXTENSION from $x509 based on given NID. my $rv = Net::SSLeay::X509_get_ext_by_NID($x509, $nid, $loc); # $x509 - value corresponding to openssl's X509 structure # $nid - (integer) NID value # $loc - (integer) position to start lookup at # # returns: position/index of extension, negative value on error # call Net::SSLeay::X509_get_ext($x509, $rv) to get the actual extension =item * X509_get_fingerprint Returns fingerprint of certificate $cert. B Does not exactly correspond to any low level API function. The implementation is basen on openssl's C. Net::SSLeay::X509_get_fingerprint($x509, $type); # $x509 - value corresponding to openssl's X509 structure # $type - (string) digest type, currently supported values: # "md5" # "sha1" # "sha256" # "ripemd160" # # returns: certificate digest - hexadecimal string (NOT binary data!) =item * X509_get_issuer_name Return an X509_NAME object representing the issuer of the certificate $cert. my $rv = Net::SSLeay::X509_get_issuer_name($cert); # $cert - value corresponding to openssl's X509 structure # # returns: value corresponding to openssl's X509_NAME structure (0 on failure) =item * X509_get_notAfter Return an object giving the time after which the certificate $cert is not valid. my $rv = Net::SSLeay::X509_get_notAfter($cert); # $cert - value corresponding to openssl's X509 structure # # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) To get human readable/printable form the return value you can use: my $time = Net::SSLeay::X509_get_notAfter($cert); print "notAfter=", Net::SSLeay::P_ASN1_TIME_get_isotime($time), "\n"; =item * X509_get_notBefore Return an object giving the time before which the certificate $cert is not valid my $rv = Net::SSLeay::X509_get_notBefore($cert); # $cert - value corresponding to openssl's X509 structure # # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) To get human readable/printable form the return value you can use: my $time = Net::SSLeay::X509_get_notBefore($cert); print "notBefore=", Net::SSLeay::P_ASN1_TIME_get_isotime($time), "\n"; =item * X509_get_subjectAltNames B Does not exactly correspond to any low level API function. Returns the list of alternative subject names from X509 certificate $cert. my @rv = Net::SSLeay::X509_get_subjectAltNames($cert); # $cert - value corresponding to openssl's X509 structure # # returns: list containing pairs - name_type (integer), name_value (string) # where name_type can be: # 0 - GEN_OTHERNAME # 1 - GEN_EMAIL # 2 - GEN_DNS # 3 - GEN_X400 # 4 - GEN_DIRNAME # 5 - GEN_EDIPARTY # 6 - GEN_URI # 7 - GEN_IPADD # 8 - GEN_RID Note: type 7 - GEN_IPADD contains the IP address as a packed binary address. =item * X509_get_subject_name Returns the subject of the certificate $cert. my $rv = Net::SSLeay::X509_get_subject_name($cert); # $cert - value corresponding to openssl's X509 structure # # returns: value corresponding to openssl's X509_NAME structure (0 on failure) =item * X509_gmtime_adj Adjust th ASN1_TIME object to the timestamp (in GMT). my $rv = Net::SSLeay::X509_gmtime_adj($s, $adj); # $s - value corresponding to openssl's ASN1_TIME structure # $adj - timestamp (seconds since 1.1.1970) # # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) B this function may fail for dates after 2038 as it is dependent on time_t size on your system (32bit time_t does not work after 2038). Consider using L instead). =item * X509_load_cert_crl_file Takes PEM file and loads all X509 certificates and X509 CRLs from that file into X509_LOOKUP structure. my $rv = Net::SSLeay::X509_load_cert_crl_file($ctx, $file, $type); # $ctx - value corresponding to openssl's X509_LOOKUP structure # $file - (string) file name # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 # if not FILETYPE_PEM then behaves as Net::SSLeay::X509_load_cert_file() # # returns: 1 on success, 0 on failure =item * X509_load_cert_file Loads/adds X509 certificate from $file to X509_LOOKUP structure my $rv = Net::SSLeay::X509_load_cert_file($ctx, $file, $type); # $ctx - value corresponding to openssl's X509_LOOKUP structure # $file - (string) file name # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 # # returns: 1 on success, 0 on failure =item * X509_load_crl_file Loads/adds X509 CRL from $file to X509_LOOKUP structure my $rv = Net::SSLeay::X509_load_crl_file($ctx, $file, $type); # $ctx - value corresponding to openssl's X509_LOOKUP structure # $file - (string) file name # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 # # returns: 1 on success, 0 on failure =item * X509_policy_level_get0_node ??? (more info needed) my $rv = Net::SSLeay::X509_policy_level_get0_node($level, $i); # $level - value corresponding to openssl's X509_POLICY_LEVEL structure # $i - (integer) index/position # # returns: value corresponding to openssl's X509_POLICY_NODE structure (0 on failure) =item * X509_policy_level_node_count ??? (more info needed) my $rv = Net::SSLeay::X509_policy_level_node_count($level); # $level - value corresponding to openssl's X509_POLICY_LEVEL structure # # returns: (integer) node count =item * X509_policy_node_get0_parent ??? (more info needed) my $rv = Net::SSLeay::X509_policy_node_get0_parent($node); # $node - value corresponding to openssl's X509_POLICY_NODE structure # # returns: value corresponding to openssl's X509_POLICY_NODE structure (0 on failure) =item * X509_policy_node_get0_policy ??? (more info needed) my $rv = Net::SSLeay::X509_policy_node_get0_policy($node); # $node - value corresponding to openssl's X509_POLICY_NODE structure # # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) =item * X509_policy_node_get0_qualifiers ??? (more info needed) my $rv = Net::SSLeay::X509_policy_node_get0_qualifiers($node); # $node - value corresponding to openssl's X509_POLICY_NODE structure # # returns: value corresponding to openssl's STACK_OF(POLICYQUALINFO) structure (0 on failure) =item * X509_policy_tree_free ??? (more info needed) Net::SSLeay::X509_policy_tree_free($tree); # $tree - value corresponding to openssl's X509_POLICY_TREE structure # # returns: no return value =item * X509_policy_tree_get0_level ??? (more info needed) my $rv = Net::SSLeay::X509_policy_tree_get0_level($tree, $i); # $tree - value corresponding to openssl's X509_POLICY_TREE structure # $i - (integer) level index # # returns: value corresponding to openssl's X509_POLICY_LEVEL structure (0 on failure) =item * X509_policy_tree_get0_policies ??? (more info needed) my $rv = Net::SSLeay::X509_policy_tree_get0_policies($tree); # $tree - value corresponding to openssl's X509_POLICY_TREE structure # # returns: value corresponding to openssl's X509_POLICY_NODE structure (0 on failure) =item * X509_policy_tree_get0_user_policies ??? (more info needed) my $rv = Net::SSLeay::X509_policy_tree_get0_user_policies($tree); # $tree - value corresponding to openssl's X509_POLICY_TREE structure # # returns: value corresponding to openssl's X509_POLICY_NODE structure (0 on failure) =item * X509_policy_tree_level_count ??? (more info needed) my $rv = Net::SSLeay::X509_policy_tree_level_count($tree); # $tree - value corresponding to openssl's X509_POLICY_TREE structure # # returns: (integer) count =item * X509_verify_cert_error_string Returns a human readable error string for verification error $n. my $rv = Net::SSLeay::X509_verify_cert_error_string($n); # $n - (long) numeric error code # # returns: error string Check openssl doc L =item * P_X509_add_extensions B not available in Net-SSLeay-1.45 and before Adds one or more X509 extensions to X509 object $x. my $rv = Net::SSLeay::P_X509_add_extensions($x, $ca_cert, $nid, $value); # $x - value corresponding to openssl's X509 structure # $ca_cert - value corresponding to openssl's X509 structure (issuer's cert - necessary for sertting NID_authority_key_identifier) # $nid - NID identifying extension to be set # $value - extension value # # returns: 1 on success, 0 on failure You can set more extensions at once: my $rv = Net::SSLeay::P_X509_add_extensions($x509, $ca_cert, &Net::SSLeay::NID_key_usage => 'digitalSignature,keyEncipherment', &Net::SSLeay::NID_subject_key_identifier => 'hash', &Net::SSLeay::NID_authority_key_identifier => 'keyid', &Net::SSLeay::NID_authority_key_identifier => 'issuer', &Net::SSLeay::NID_basic_constraints => 'CA:FALSE', &Net::SSLeay::NID_ext_key_usage => 'serverAuth,clientAuth', &Net::SSLeay::NID_netscape_cert_type => 'server', &Net::SSLeay::NID_subject_alt_name => 'DNS:s1.dom.com,DNS:s2.dom.com,DNS:s3.dom.com', ); =item * P_X509_copy_extensions B not available in Net-SSLeay-1.45 and before Copies X509 extensions from X509_REQ object to X509 object - handy when you need to turn X509_REQ into X509 certificate. Net::SSLeay::P_X509_copy_extensions($x509_req, $x509, $override); # $x509_req - value corresponding to openssl's X509_REQ structure # $x509 - value corresponding to openssl's X509 structure # $override - (integer) flag indication whether to override already existing items in $x509 (default 1) # # returns: 1 on success, 0 on failure =item * P_X509_get_crl_distribution_points B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Get the list of CRL distribution points from X509 certificate. my @cdp = Net::SSLeay::P_X509_get_crl_distribution_points($x509); # $x509 - value corresponding to openssl's X509 structure # # returns: list of distribution points (usually URLs) =item * P_X509_get_ext_key_usage B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Gets the list of extended key usage of given X509 certificate $cert. my @ext_usage = Net::SSLeay::P_X509_get_ext_key_usage($cert, $format); # $cert - value corresponding to openssl's X509 structure # $format - choose type of return values: 0=OIDs, 1=NIDs, 2=shortnames, 3=longnames # # returns: list of values Examples: my @extkeyusage_oid = Net::SSLeay::P_X509_get_ext_key_usage($x509,0); # returns for example: ("1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2") my @extkeyusage_nid = Net::SSLeay::P_X509_get_ext_key_usage($x509,1); # returns for example: (129, 130) my @extkeyusage_sn = Net::SSLeay::P_X509_get_ext_key_usage($x509,2); # returns for example: ("serverAuth", "clientAuth") my @extkeyusage_ln = Net::SSLeay::P_X509_get_ext_key_usage($x509,3); # returns for example: ("TLS Web Server Authentication", "TLS Web Client Authentication") =item * P_X509_get_key_usage B not available in Net-SSLeay-1.45 and before Gets the list of key usage of given X509 certificate $cert. my @keyusage = Net::SSLeay::P_X509_get_key_usage($cert); # $cert - value corresponding to openssl's X509 structure # # returns: list of key usage values which can be none, one or more from the following list: # "digitalSignature" # "nonRepudiation" # "keyEncipherment" # "dataEncipherment" # "keyAgreement" # "keyCertSign" # "cRLSign" # "encipherOnly" # "decipherOnly" =item * P_X509_get_netscape_cert_type B not available in Net-SSLeay-1.45 and before Gets the list of Netscape cert types of given X509 certificate $cert. Net::SSLeay::P_X509_get_netscape_cert_type($cert); # $cert - value corresponding to openssl's X509 structure # # returns: list of Netscape type values which can be none, one or more from the following list: # "client" # "server" # "email" # "objsign" # "reserved" # "sslCA" # "emailCA" # "objCA" =item * P_X509_get_pubkey_alg B not available in Net-SSLeay-1.45 and before Returns ASN1_OBJECT corresponding to X509 certificate public key algorithm. my $rv = Net::SSLeay::P_X509_get_pubkey_alg($x); # $x - value corresponding to openssl's X509 structure # # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) To get textual representation use: my $alg = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_pubkey_alg($x509)); # returns for example: "rsaEncryption" =item * P_X509_get_signature_alg B not available in Net-SSLeay-1.45 and before Returns ASN1_OBJECT corresponding to X509 signarite key algorithm. my $rv = Net::SSLeay::P_X509_get_signature_alg($x); # $x - value corresponding to openssl's X509 structure # # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) To get textual representation use: my $alg = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_signature_alg($x509)) # returns for example: "sha1WithRSAEncryption" =item * sk_X509_new_null Returns a new, empty, STACK_OF(X509) structure. my $rv = Net::SSLeay::sk_X509_new_null(); # # returns: value corresponding to openssl's STACK_OF(X509) structure =item * sk_X509_push Pushes an X509 structure onto a STACK_OF(X509) structure. my $rv = Net::SSLeay::sk_X509_push($sk_x509, $x509); # $sk_x509 - value corresponding to openssl's STACK_OF(X509) structure # $x509 - value corresponding to openssl's X509 structure # # returns: 1 if successful, 0 if unsuccessful =back =head3 Low level API: X509_REQ_* related functions =over =item * X509_REQ_new B not available in Net-SSLeay-1.45 and before Creates a new X509_REQ structure. my $rv = Net::SSLeay::X509_REQ_new(); # # returns: value corresponding to openssl's X509_REQ structure (0 on failure) =item * X509_REQ_free B not available in Net-SSLeay-1.45 and before Free an allocated X509_REQ structure. Net::SSLeay::X509_REQ_free($x); # $x - value corresponding to openssl's X509_REQ structure # # returns: no return value =item * X509_REQ_add1_attr_by_NID B not available in Net-SSLeay-1.45 and before Adds an attribute whose name is defined by a NID $nid. The field value to be added is in $bytes. my $rv = Net::SSLeay::X509_REQ_add1_attr_by_NID($req, $nid, $type, $bytes); # $req - value corresponding to openssl's X509_REQ structure # $nid - (integer) NID value # $type - (integer) type of data in $bytes (see below) # $bytes - data to be set # # returns: 1 on success, 0 on failure # values for $type - use constants: &Net::SSLeay::MBSTRING_UTF8 - $bytes contains utf8 encoded data &Net::SSLeay::MBSTRING_ASC - $bytes contains ASCII data =item * X509_REQ_digest B not available in Net-SSLeay-1.45 and before Computes digest/fingerprint of X509_REQ $data using $type hash function. my $digest_value = Net::SSLeay::X509_REQ_digest($data, $type); # $data - value corresponding to openssl's X509_REQ structure # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() # # returns: hash value (binary) #to get printable (hex) value of digest use: print unpack('H*', $digest_value); =item * X509_REQ_get_attr_by_NID B not available in Net-SSLeay-1.45 and before Retrieve the next index matching $nid after $lastpos ($lastpos should initially be set to -1). my $rv = Net::SSLeay::X509_REQ_get_attr_by_NID($req, $nid, $lastpos=-1); # $req - value corresponding to openssl's X509_REQ structure # $nid - (integer) NID value # $lastpos - [optional] (integer) index where to start search (default -1) # # returns: index (-1 if there are no more entries) Note: use L to get the actual attribute value - e.g. my $index = Net::SSLeay::X509_REQ_get_attr_by_NID($req, $nid); my @attr_values = Net::SSLeay::P_X509_REQ_get_attr($req, $index); =item * X509_REQ_get_attr_by_OBJ B not available in Net-SSLeay-1.45 and before Retrieve the next index matching $obj after $lastpos ($lastpos should initially be set to -1). my $rv = Net::SSLeay::X509_REQ_get_attr_by_OBJ($req, $obj, $lastpos=-1); # $req - value corresponding to openssl's X509_REQ structure # $obj - value corresponding to openssl's ASN1_OBJECT structure # $lastpos - [optional] (integer) index where to start search (default -1) # # returns: index (-1 if there are no more entries) Note: use L to get the actual attribute value - e.g. my $index = Net::SSLeay::X509_REQ_get_attr_by_NID($req, $nid); my @attr_values = Net::SSLeay::P_X509_REQ_get_attr($req, $index); =item * X509_REQ_get_attr_count B not available in Net-SSLeay-1.45 and before Returns the total number of attributes in $req. my $rv = Net::SSLeay::X509_REQ_get_attr_count($req); # $req - value corresponding to openssl's X509_REQ structure # # returns: (integer) items count =item * X509_REQ_get_pubkey B not available in Net-SSLeay-1.45 and before Returns public key corresponding to given X509_REQ object $x. my $rv = Net::SSLeay::X509_REQ_get_pubkey($x); # $x - value corresponding to openssl's X509_REQ structure # # returns: value corresponding to openssl's EVP_PKEY structure (0 on failure) =item * X509_REQ_get_subject_name B not available in Net-SSLeay-1.45 and before Returns X509_NAME object corresponding to subject name of given X509_REQ object $x. my $rv = Net::SSLeay::X509_REQ_get_subject_name($x); # $x - value corresponding to openssl's X509_REQ structure # # returns: value corresponding to openssl's X509_NAME structure (0 on failure) =item * X509_REQ_get_version B not available in Net-SSLeay-1.45 and before Returns 'version' value for given X509_REQ object $x. my $rv = Net::SSLeay::X509_REQ_get_version($x); # $x - value corresponding to openssl's X509_REQ structure # # returns: (integer) version e.g. 0 = "version 1" =item * X509_REQ_set_pubkey B not available in Net-SSLeay-1.45 and before Sets public key of given X509_REQ object $x to $pkey. my $rv = Net::SSLeay::X509_REQ_set_pubkey($x, $pkey); # $x - value corresponding to openssl's X509_REQ structure # $pkey - value corresponding to openssl's EVP_PKEY structure # # returns: 1 on success, 0 on failure =item * X509_REQ_set_subject_name B not available in Net-SSLeay-1.45 and before Sets subject name of given X509_REQ object $x to X509_NAME object $name. my $rv = Net::SSLeay::X509_REQ_set_subject_name($x, $name); # $x - value corresponding to openssl's X509_REQ structure # $name - value corresponding to openssl's X509_NAME structure # # returns: 1 on success, 0 on failure =item * X509_REQ_set_version B not available in Net-SSLeay-1.45 and before Sets 'version' of given X509_REQ object $x to $version. my $rv = Net::SSLeay::X509_REQ_set_version($x, $version); # $x - value corresponding to openssl's X509_REQ structure # $version - (integer) e.g. 0 = "version 1" # # returns: 1 on success, 0 on failure =item * X509_REQ_sign B not available in Net-SSLeay-1.45 and before Sign X509_REQ object $x with private key $pk (using digest algorithm $md). my $rv = Net::SSLeay::X509_REQ_sign($x, $pk, $md); # $x - value corresponding to openssl's X509_REQ structure # $pk - value corresponding to openssl's EVP_PKEY structure (requestor's private key) # $md - value corresponding to openssl's EVP_MD structure # # returns: 1 on success, 0 on failure =item * X509_REQ_verify B not available in Net-SSLeay-1.45 and before Verifies X509_REQ object $x using public key $r (pubkey of requesting party). my $rv = Net::SSLeay::X509_REQ_verify($x, $r); # $x - value corresponding to openssl's X509_REQ structure # $r - value corresponding to openssl's EVP_PKEY structure # # returns: 0 - verify failure, 1 - verify OK, <0 - error =item * P_X509_REQ_add_extensions B not available in Net-SSLeay-1.45 and before Adds one or more X509 extensions to X509_REQ object $x. my $rv = Net::SSLeay::P_X509_REQ_add_extensions($x, $nid, $value); # $x - value corresponding to openssl's X509_REQ structure # $nid - NID identifying extension to be set # $value - extension value # # returns: 1 on success, 0 on failure You can set more extensions at once: my $rv = Net::SSLeay::P_X509_REQ_add_extensions($x509_req, &Net::SSLeay::NID_key_usage => 'digitalSignature,keyEncipherment', &Net::SSLeay::NID_basic_constraints => 'CA:FALSE', &Net::SSLeay::NID_ext_key_usage => 'serverAuth,clientAuth', &Net::SSLeay::NID_netscape_cert_type => 'server', &Net::SSLeay::NID_subject_alt_name => 'DNS:s1.com,DNS:s2.com', &Net::SSLeay::NID_crl_distribution_points => 'URI:http://pki.com/crl1,URI:http://pki.com/crl2', ); =item * P_X509_REQ_get_attr B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Returns attribute value for X509_REQ's attribute at index $n. Net::SSLeay::P_X509_REQ_get_attr($req, $n); # $req - value corresponding to openssl's X509_REQ structure # $n - (integer) attribute index # # returns: value corresponding to openssl's ASN1_STRING structure =back =head3 Low level API: X509_CRL_* related functions =over =item * X509_CRL_new B not available in Net-SSLeay-1.45 and before Creates a new X509_CRL structure. my $rv = Net::SSLeay::X509_CRL_new(); # # returns: value corresponding to openssl's X509_CRL structure (0 on failure) =item * X509_CRL_free B not available in Net-SSLeay-1.45 and before Free an allocated X509_CRL structure. Net::SSLeay::X509_CRL_free($x); # $x - value corresponding to openssl's X509_CRL structure # # returns: no return value =item * X509_CRL_digest B not available in Net-SSLeay-1.45 and before Computes digest/fingerprint of X509_CRL $data using $type hash function. my $digest_value = Net::SSLeay::X509_CRL_digest($data, $type); # $data - value corresponding to openssl's X509_CRL structure # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() # # returns: hash value (binary) Example: my $x509_crl my $md = Net::SSLeay::EVP_get_digestbyname("sha1"); my $digest_value = Net::SSLeay::X509_CRL_digest($x509_crl, $md); #to get printable (hex) value of digest use: print "digest=", unpack('H*', $digest_value), "\n"; =item * X509_CRL_get_ext B not available in Net-SSLeay-1.54 and before Returns X509_EXTENSION from $x509 based on given position/index. my $rv = Net::SSLeay::X509_CRL_get_ext($x509, $index); # $x509 - value corresponding to openssl's X509_CRL structure # $index - (integer) position/index of extension within $x509 # # returns: value corresponding to openssl's X509_EXTENSION structure (0 on failure) =item * X509_CRL_get_ext_by_NID B not available in Net-SSLeay-1.54 and before Returns X509_EXTENSION from $x509 based on given NID. my $rv = Net::SSLeay::X509_CRL_get_ext_by_NID($x509, $nid, $loc); # $x509 - value corresponding to openssl's X509_CRL structure # $nid - (integer) NID value # $loc - (integer) position to start lookup at # # returns: position/index of extension, negative value on error # call Net::SSLeay::X509_CRL_get_ext($x509, $rv) to get the actual extension =item * X509_CRL_get_ext_count B not available in Net-SSLeay-1.54 and before Returns the total number of extensions in X509_CRL object $x. my $rv = Net::SSLeay::X509_CRL_get_ext_count($x); # $x - value corresponding to openssl's X509_CRL structure # # returns: count of extensions =item * X509_CRL_get_issuer B not available in Net-SSLeay-1.45 and before Returns X509_NAME object corresponding to the issuer of X509_CRL $x. my $rv = Net::SSLeay::X509_CRL_get_issuer($x); # $x - value corresponding to openssl's X509_CRL structure # # returns: value corresponding to openssl's X509_NAME structure (0 on failure) See other C functions to get more info from X509_NAME structure. =item * X509_CRL_get_lastUpdate B not available in Net-SSLeay-1.45 and before Returns 'lastUpdate' date-time value of X509_CRL object $x. my $rv = Net::SSLeay::X509_CRL_get_lastUpdate($x); # $x - value corresponding to openssl's X509_CRL structure # # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) =item * X509_CRL_get_nextUpdate B not available in Net-SSLeay-1.45 and before Returns 'nextUpdate' date-time value of X509_CRL object $x. my $rv = Net::SSLeay::X509_CRL_get_nextUpdate($x); # $x - value corresponding to openssl's X509_CRL structure # # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) =item * X509_CRL_get_version B not available in Net-SSLeay-1.45 and before Returns 'version' value of given X509_CRL structure $x. my $rv = Net::SSLeay::X509_CRL_get_version($x); # $x - value corresponding to openssl's X509_CRL structure # # returns: (integer) version =item * X509_CRL_set_issuer_name B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Sets the issuer of X509_CRL object $x to X509_NAME object $name. my $rv = Net::SSLeay::X509_CRL_set_issuer_name($x, $name); # $x - value corresponding to openssl's X509_CRL structure # $name - value corresponding to openssl's X509_NAME structure # # returns: 1 on success, 0 on failure =item * X509_CRL_set_lastUpdate B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Sets 'lastUpdate' value of X509_CRL object $x to $tm. my $rv = Net::SSLeay::X509_CRL_set_lastUpdate($x, $tm); # $x - value corresponding to openssl's X509_CRL structure # $tm - value corresponding to openssl's ASN1_TIME structure # # returns: 1 on success, 0 on failure =item * X509_CRL_set_nextUpdate B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Sets 'nextUpdate' value of X509_CRL object $x to $tm. my $rv = Net::SSLeay::X509_CRL_set_nextUpdate($x, $tm); # $x - value corresponding to openssl's X509_CRL structure # $tm - value corresponding to openssl's ASN1_TIME structure # # returns: 1 on success, 0 on failure =item * X509_CRL_set_version B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Sets 'version' value of given X509_CRL structure $x to $version. my $rv = Net::SSLeay::X509_CRL_set_version($x, $version); # $x - value corresponding to openssl's X509_CRL structure # $version - (integer) version number (1 = version 2 CRL) # # returns: 1 on success, 0 on failure Note that if you want to use any X509_CRL extension you need to set "version 2 CRL" - C. =item * X509_CRL_sign B not available in Net-SSLeay-1.45 and before Sign X509_CRL object $x with private key $pkey (using digest algorithm $md). my $rv = Net::SSLeay::X509_CRL_sign($x, $pkey, $md); # $x - value corresponding to openssl's X509_CRL structure # $pkey - value corresponding to openssl's EVP_PKEY structure # $md - value corresponding to openssl's EVP_MD structure # # returns: 1 on success, 0 on failure =item * X509_CRL_sort B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Sorts the data of X509_CRL object so it will be written in serial number order. my $rv = Net::SSLeay::X509_CRL_sort($x); # $x - value corresponding to openssl's X509_CRL structure # # returns: 1 on success, 0 on failure =item * X509_CRL_verify B not available in Net-SSLeay-1.45 and before Verifies X509_CRL object $a using public key $r (pubkey of issuing CA). my $rv = Net::SSLeay::X509_CRL_verify($a, $r); # $a - value corresponding to openssl's X509_CRL structure # $r - value corresponding to openssl's EVP_PKEY structure # # returns: 0 - verify failure, 1 - verify OK, <0 - error =item * P_X509_CRL_add_revoked_serial_hex B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Adds given serial number $serial_hex to X509_CRL object $crl. Net::SSLeay::P_X509_CRL_add_revoked_serial_hex($crl, $serial_hex, $rev_time, $reason_code, $comp_time); # $crl - value corresponding to openssl's X509_CRL structure # $serial_hex - string (hexadecimal) representation of serial number # $rev_time - (revocation time) value corresponding to openssl's ASN1_TIME structure # $reason_code - [optional] (integer) reason code (see below) - default 0 # $comp_time - [optional] (compromise time) value corresponding to openssl's ASN1_TIME structure # # returns: no return value reason codes: 0 - unspecified 1 - keyCompromise 2 - CACompromise 3 - affiliationChanged 4 - superseded 5 - cessationOfOperation 6 - certificateHold 7 - removeFromCRL =item * P_X509_CRL_get_serial B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Returns serial number of X509_CRL object. my $rv = Net::SSLeay::P_X509_CRL_get_serial($crl); # $crl - value corresponding to openssl's X509_CRL structure # # returns: value corresponding to openssl's ASN1_INTEGER structure (0 on failure) =item * P_X509_CRL_set_serial B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 Sets serial number of X509_CRL object to $crl_number. my $rv = Net::SSLeay::P_X509_CRL_set_serial($crl, $crl_number); # $crl - value corresponding to openssl's X509_CRL structure # $crl_number - value corresponding to openssl's ASN1_INTEGER structure # # returns: 1 on success, 0 on failure =back =head3 Low level API: X509_EXTENSION_* related functions =over =item * X509_EXTENSION_get_critical B not available in Net-SSLeay-1.45 and before Returns 'critical' flag of given X509_EXTENSION object $ex. my $rv = Net::SSLeay::X509_EXTENSION_get_critical($ex); # $ex - value corresponding to openssl's X509_EXTENSION structure # # returns: (integer) 1 - critical, 0 - noncritical =item * X509_EXTENSION_get_data B not available in Net-SSLeay-1.45 and before Returns value (raw data) of X509_EXTENSION object $ne. my $rv = Net::SSLeay::X509_EXTENSION_get_data($ne); # $ne - value corresponding to openssl's X509_EXTENSION structure # # returns: value corresponding to openssl's ASN1_OCTET_STRING structure (0 on failure) Note: you can use L to convert ASN1_OCTET_STRING into perl scalar variable. =item * X509_EXTENSION_get_object B not available in Net-SSLeay-1.45 and before Returns OID (ASN1_OBJECT) of X509_EXTENSION object $ne. my $rv = Net::SSLeay::X509_EXTENSION_get_object($ex); # $ex - value corresponding to openssl's X509_EXTENSION structure # # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) =item * X509V3_EXT_print B not available in Net-SSLeay-1.45 and before Returns string representation of given X509_EXTENSION object $ext. Net::SSLeay::X509V3_EXT_print($ext, $flags, $utf8_decode); # $ext - value corresponding to openssl's X509_EXTENSION structure # $flags - [optional] (integer) Currently the flag argument is unused and should be set to 0 # $utf8_decode - [optional] 0 or 1 whether the returned value should be utf8 decoded (default=0) # # returns: no return value =item * X509V3_EXT_d2i Parses an extension and returns its internal structure. my $rv = Net::SSLeay::X509V3_EXT_d2i($ext); # $ext - value corresponding to openssl's X509_EXTENSION structure # # returns: pointer ??? =back =head3 Low level API: X509_NAME_* related functions =over =item * X509_NAME_ENTRY_get_data B not available in Net-SSLeay-1.45 and before Retrieves the field value of $ne in and ASN1_STRING structure. my $rv = Net::SSLeay::X509_NAME_ENTRY_get_data($ne); # $ne - value corresponding to openssl's X509_NAME_ENTRY structure # # returns: value corresponding to openssl's ASN1_STRING structure (0 on failure) Check openssl doc L =item * X509_NAME_ENTRY_get_object B not available in Net-SSLeay-1.45 and before Retrieves the field name of $ne in and ASN1_OBJECT structure. my $rv = Net::SSLeay::X509_NAME_ENTRY_get_object($ne); # $ne - value corresponding to openssl's X509_NAME_ENTRY structure # # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) Check openssl doc L =item * X509_NAME_new B not available in Net-SSLeay-1.55 and before; requires at least openssl-0.9.5 Creates a new X509_NAME structure. Adds a field whose name is defined by a string $field. The field value to be added is in $bytes. my $rv = Net::SSLeay::X509_NAME_new(); # # returns: value corresponding to openssl's X509_NAME structure (0 on failure) =item * X509_NAME_hash B not available in Net-SSLeay-1.55 and before; requires at least openssl-0.9.5 Sort of a checksum of issuer name $name. The result is not a full hash (e.g. sha-1), it is kind-of-a-hash truncated to the size of 'unsigned long' (32 bits). The resulting value might differ across different openssl versions for the same X509 certificate. my $rv = Net::SSLeay::X509_NAME_hash($name); # $name - value corresponding to openssl's X509_NAME structure # # returns: number representing checksum =item * X509_NAME_add_entry_by_txt B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.5 Adds a field whose name is defined by a string $field. The field value to be added is in $bytes. my $rv = Net::SSLeay::X509_NAME_add_entry_by_txt($name, $field, $type, $bytes, $len, $loc, $set); # $name - value corresponding to openssl's X509_NAME structure # $field - (string) field definition (name) - e.g. "organizationName" # $type - (integer) type of data in $bytes (see below) # $bytes - data to be set # $loc - [optional] (integer) index where the new entry is inserted: if it is -1 (default) it is appended # $set - [optional] (integer) determines how the new type is added. If it is 0 (default) a new RDN is created # # returns: 1 on success, 0 on failure # values for $type - use constants: &Net::SSLeay::MBSTRING_UTF8 - $bytes contains utf8 encoded data &Net::SSLeay::MBSTRING_ASC - $bytes contains ASCII data Unicode note: when passing non-ascii (unicode) string in $bytes do not forget to set C<$flags = &Net::SSLeay::MBSTRING_UTF8> and encode the perl $string via C<$bytes = encode('utf-8', $string)>. Check openssl doc L =item * X509_NAME_add_entry_by_NID B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.5 Adds a field whose name is defined by a NID $nid. The field value to be added is in $bytes. my $rv = Net::SSLeay::X509_NAME_add_entry_by_NID($name, $nid, $type, $bytes, $len, $loc, $set); # $name - value corresponding to openssl's X509_NAME structure # $nid - (integer) field definition - NID value # $type - (integer) type of data in $bytes (see below) # $bytes - data to be set # $loc - [optional] (integer) index where the new entry is inserted: if it is -1 (default) it is appended # $set - [optional] (integer) determines how the new type is added. If it is 0 (default) a new RDN is created # # returns: 1 on success, 0 on failure Check openssl doc L =item * X509_NAME_add_entry_by_OBJ B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.5 Adds a field whose name is defined by a object (OID) $obj . The field value to be added is in $bytes. my $rv = Net::SSLeay::X509_NAME_add_entry_by_OBJ($name, $obj, $type, $bytes, $len, $loc, $set); # $name - value corresponding to openssl's X509_NAME structure # $obj - field definition - value corresponding to openssl's ASN1_OBJECT structure # $type - (integer) type of data in $bytes (see below) # $bytes - data to be set # $loc - [optional] (integer) index where the new entry is inserted: if it is -1 (default) it is appended # $set - [optional] (integer) determines how the new type is added. If it is 0 (default) a new RDN is created # # returns: 1 on success, 0 on failure Check openssl doc L =item * X509_NAME_cmp B not available in Net-SSLeay-1.45 and before Compares two X509_NAME obejcts. my $rv = Net::SSLeay::X509_NAME_cmp($a, $b); # $a - value corresponding to openssl's X509_NAME structure # $b - value corresponding to openssl's X509_NAME structure # # returns: 0 if $a matches $b; non zero otherwise =item * X509_NAME_digest B not available in Net-SSLeay-1.45 and before Computes digest/fingerprint of X509_NAME $data using $type hash function. my $digest_value = Net::SSLeay::X509_NAME_digest($data, $type); # $data - value corresponding to openssl's X509_NAME structure # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() # # returns: hash value (binary) #to get printable (hex) value of digest use: print unpack('H*', $digest_value); =item * X509_NAME_entry_count B not available in Net-SSLeay-1.45 and before Returns the total number of entries in $name. my $rv = Net::SSLeay::X509_NAME_entry_count($name); # $name - value corresponding to openssl's X509_NAME structure # # returns: (integer) entries count Check openssl doc L =item * X509_NAME_get_entry B not available in Net-SSLeay-1.45 and before Retrieves the X509_NAME_ENTRY from $name corresponding to index $loc. Acceptable values for $loc run from 0 to C. The value returned is an internal pointer which must not be freed. my $rv = Net::SSLeay::X509_NAME_get_entry($name, $loc); # $name - value corresponding to openssl's X509_NAME structure # $loc - (integer) index of wanted entry # # returns: value corresponding to openssl's X509_NAME_ENTRY structure (0 on failure) Check openssl doc L =item * X509_NAME_print_ex B not available in Net-SSLeay-1.45 and before Returns a string with human readable version of $name. Net::SSLeay::X509_NAME_print_ex($name, $flags, $utf8_decode); # $name - value corresponding to openssl's X509_NAME structure # $flags - [optional] conversion flags (default XN_FLAG_RFC2253) - see below # $utf8_decode - [optional] 0 or 1 whether the returned value should be utf8 decoded (default=0) # # returns: string representation of $name #available conversion flags - use constants: &Net::SSLeay::XN_FLAG_COMPAT &Net::SSLeay::XN_FLAG_DN_REV &Net::SSLeay::XN_FLAG_DUMP_UNKNOWN_FIELDS &Net::SSLeay::XN_FLAG_FN_ALIGN &Net::SSLeay::XN_FLAG_FN_LN &Net::SSLeay::XN_FLAG_FN_MASK &Net::SSLeay::XN_FLAG_FN_NONE &Net::SSLeay::XN_FLAG_FN_OID &Net::SSLeay::XN_FLAG_FN_SN &Net::SSLeay::XN_FLAG_MULTILINE &Net::SSLeay::XN_FLAG_ONELINE &Net::SSLeay::XN_FLAG_RFC2253 &Net::SSLeay::XN_FLAG_SEP_COMMA_PLUS &Net::SSLeay::XN_FLAG_SEP_CPLUS_SPC &Net::SSLeay::XN_FLAG_SEP_MASK &Net::SSLeay::XN_FLAG_SEP_MULTILINE &Net::SSLeay::XN_FLAG_SEP_SPLUS_SPC &Net::SSLeay::XN_FLAG_SPC_EQ Most likely you will be fine with default: Net::SSLeay::X509_NAME_print_ex($name, &Net::SSLeay::XN_FLAG_RFC2253); Or you might want RFC2253-like output without utf8 chars escaping: use Net::SSLeay qw/XN_FLAG_RFC2253 ASN1_STRFLGS_ESC_MSB/; my $flag_rfc22536_utf8 = (XN_FLAG_RFC2253) & (~ ASN1_STRFLGS_ESC_MSB); my $result = Net::SSLeay::X509_NAME_print_ex($name, $flag_rfc22536_utf8, 1); Check openssl doc L =item * X509_NAME_get_text_by_NID Retrieves the text from the first entry in name which matches $nid, if no such entry exists -1 is returned. B this is a legacy function which has various limitations which makes it of minimal use in practice. It can only find the first matching entry and will copy the contents of the field verbatim: this can be highly confusing if the target is a multicharacter string type like a BMPString or a UTF8String. Net::SSLeay::X509_NAME_get_text_by_NID($name, $nid); # $name - value corresponding to openssl's X509_NAME structure # $nid - NID value (integer) # # returns: text value Check openssl doc L =item * X509_NAME_oneline Return an ASCII version of $name. Net::SSLeay::X509_NAME_oneline($name); # $name - value corresponding to openssl's X509_NAME structure # # returns: (string) ASCII version of $name Check openssl doc L =item * sk_X509_NAME_free Free an allocated STACK_OF(X509_NAME) structure. Net::SSLeay::sk_X509_NAME_free($sk); # $sk - value corresponding to openssl's STACK_OF(X509_NAME) structure # # returns: no return value =item * sk_X509_NAME_num Return number of items in STACK_OF(X509_NAME) my $rv = Net::SSLeay::sk_X509_NAME_num($sk); # $sk - value corresponding to openssl's STACK_OF(X509_NAME) structure # # returns: number of items =item * sk_X509_NAME_value Returns X509_NAME from position $index in STACK_OF(X509_NAME) my $rv = Net::SSLeay::sk_X509_NAME_value($sk, $i); # $sk - value corresponding to openssl's STACK_OF(X509_NAME) structure # $i - (integer) index/position # # returns: value corresponding to openssl's X509_NAME structure (0 on failure) =item * add_file_cert_subjects_to_stack Add a file of certs to a stack. All certs in $file that are not already in the $stackCAs will be added. my $rv = Net::SSLeay::add_file_cert_subjects_to_stack($stackCAs, $file); # $stackCAs - value corresponding to openssl's STACK_OF(X509_NAME) structure # $file - (string) filename # # returns: 1 on success, 0 on failure =item * add_dir_cert_subjects_to_stack Add a directory of certs to a stack. All certs in $dir that are not already in the $stackCAs will be added. my $rv = Net::SSLeay::add_dir_cert_subjects_to_stack($stackCAs, $dir); # $stackCAs - value corresponding to openssl's STACK_OF(X509_NAME) structure # $dir - (string) the directory to append from. All files in this directory will be examined as potential certs. Any that are acceptable to SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be included. # # returns: 1 on success, 0 on failure =back =head3 Low level API: X509_STORE_* related functions =over =item * X509_STORE_CTX_new returns a newly initialised X509_STORE_CTX structure. =item * X509_STORE_CTX_init X509_STORE_CTX_init() sets up an X509_STORE_CTX for a subsequent verification operation. It must be called before each call to X509_verify_cert(). Net::SSLeay::X509_STORE_CTX_init($x509_store_ctx, $x509_store, $x509, $chain); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure (required) # $x509_store - value corresponding to openssl's X509_STORE structure (optional) # $x509 - value corresponding to openssl's X509 structure (optional) # $chain - value corresponding to openssl's STACK_OF(X509) structure (optional) Check openssl doc L =item * X509_STORE_CTX_free Frees an X509_STORE_CTX structure. Net::SSLeay::X509_STORE_CTX_free($x509_store_ctx); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure =item * X509_verify_cert The X509_verify_cert() function attempts to discover and validate a certificate chain based on parameters in ctx. A complete description of the process is contained in the verify(1) manual page. If this function returns 0, use X509_STORE_CTX_get_error to get additional error information. my $rv = Net::SSLeay::X509_verify_cert($x509_store_ctx); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure # # returns: 1 if a complete chain can be built and validated, otherwise 0 Check openssl doc L =item * X509_STORE_CTX_get_current_cert Returns the certificate in ctx which caused the error or 0 if no certificate is relevant. my $rv = Net::SSLeay::X509_STORE_CTX_get_current_cert($x509_store_ctx); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure # # returns: value corresponding to openssl's X509 structure (0 on failure) Check openssl doc L =item * X509_STORE_CTX_get_error Returns the error code of $ctx. my $rv = Net::SSLeay::X509_STORE_CTX_get_error($x509_store_ctx); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure # # returns: (integer) error code For more info about erro code values check function L. Check openssl doc L =item * X509_STORE_CTX_get_error_depth Returns the depth of the error. This is a non-negative integer representing where in the certificate chain the error occurred. If it is zero it occurred in the end entity certificate, one if it is the certificate which signed the end entity certificate and so on. my $rv = Net::SSLeay::X509_STORE_CTX_get_error_depth($x509_store_ctx); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure # # returns: (integer) depth Check openssl doc L =item * X509_STORE_CTX_get_ex_data Is used to retrieve the information for $idx from $x509_store_ctx. my $rv = Net::SSLeay::X509_STORE_CTX_get_ex_data($x509_store_ctx, $idx); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure # $idx - (integer) index for application specific data # # returns: pointer to ??? =item * X509_STORE_CTX_set_ex_data Is used to store application data at arg for idx into $x509_store_ctx. my $rv = Net::SSLeay::X509_STORE_CTX_set_ex_data($x509_store_ctx, $idx, $data); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure # $idx - (integer) ??? # $data - (pointer) ??? # # returns: 1 on success, 0 on failure =item * X509_STORE_CTX_set_cert Sets the certificate to be verified in $x509_store_ctx to $x. Net::SSLeay::X509_STORE_CTX_set_cert($x509_store_ctx, $x); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure # $x - value corresponding to openssl's X509 structure # # returns: no return value Check openssl doc L =item * X509_STORE_new Returns a newly initialized X509_STORE structure. my $rv = Net::SSLeay::X509_STORE_new(); # # returns: value corresponding to openssl's X509_STORE structure (0 on failure) =item * X509_STORE_free Frees an X509_STORE structure Net::SSLeay::X509_STORE_free($x509_store); # $x509_store - value corresponding to openssl's X509_STORE structure =item * X509_STORE_add_lookup Adds a lookup to an X509_STORE for a given lookup method. my $method = &Net::SSLeay::X509_LOOKUP_hash_dir; my $rv = Net::SSLeay::X509_STORE_add_lookup($x509_store, $method); # $method - value corresponding to openssl's X509_LOOKUP_METHOD structure # $x509_store - value corresponding to openssl's X509_STORE structure # # returns: value corresponding to openssl's X509_LOOKUP structure Check openssl doc L =item * X509_STORE_CTX_set_error Sets the error code of $ctx to $s. For example it might be used in a verification callback to set an error based on additional checks. Net::SSLeay::X509_STORE_CTX_set_error($x509_store_ctx, $s); # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure # $s - (integer) error id # # returns: no return value Check openssl doc L =item * X509_STORE_add_cert Adds X509 certificate $x into the X509_STORE $store. my $rv = Net::SSLeay::X509_STORE_add_cert($store, $x); # $store - value corresponding to openssl's X509_STORE structure # $x - value corresponding to openssl's X509 structure # # returns: 1 on success, 0 on failure =item * X509_STORE_add_crl Adds X509 CRL $x into the X509_STORE $store. my $rv = Net::SSLeay::X509_STORE_add_crl($store, $x); # $store - value corresponding to openssl's X509_STORE structure # $x - value corresponding to openssl's X509_CRL structure # # returns: 1 on success, 0 on failure =item * X509_STORE_set1_param ??? (more info needed) my $rv = Net::SSLeay::X509_STORE_set1_param($store, $pm); # $store - value corresponding to openssl's X509_STORE structure # $pm - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: 1 on success, 0 on failure =item * X509_LOOKUP_hash_dir Returns an X509_LOOKUP structure that instructs an X509_STORE to load files from a directory containing certificates with filenames in the format I or crls with filenames in the format IBI my $rv = Net::SSLeay::X509_LOOKUP_hash_dir(); # # returns: value corresponding to openssl's X509_LOOKUP_METHOD structure, with the hashed directory method Check openssl doc L =item * X509_LOOKUP_add_dir Add a directory to an X509_LOOKUP structure, usually obtained from X509_STORE_add_lookup. my $method = &Net::SSLeay::X509_LOOKUP_hash_dir; my $lookup = Net::SSLeay::X509_STORE_add_lookup($x509_store, $method); my $type = &Net::SSLeay::X509_FILETYPE_PEM; Net::SSLeay::X509_LOOKUP_add_dir($lookup, $dir, $type); # $lookup - value corresponding to openssl's X509_LOOKUP structure # $dir - string path to a directory s# $type - constant corresponding to the type of file in the directory - can be X509_FILETYPE_PEM, X509_FILETYPE_DEFAULT, or X509_FILETYPE_ASN1 =item * X509_STORE_set_flags Net::SSLeay::X509_STORE_set_flags($ctx, $flags); # $ctx - value corresponding to openssl's X509_STORE structure # $flags - (unsigned long) flags to be set (bitmask) # # returns: no return value #to create $flags value use corresponding constants like $flags = Net::SSLeay::X509_V_FLAG_CRL_CHECK(); For more details about $flags bitmask see L. =item * X509_STORE_set_purpose Net::SSLeay::X509_STORE_set_purpose($ctx, $purpose); # $ctx - value corresponding to openssl's X509_STORE structure # $purpose - (integer) purpose identifier # # returns: no return value For more details about $purpose identifier check L. =item * X509_STORE_set_trust Net::SSLeay::X509_STORE_set_trust($ctx, $trust); # $ctx - value corresponding to openssl's X509_STORE structure # $trust - (integer) trust identifier # # returns: no return value For more details about $trust identifier check L. =back =head3 Low Level API: X509_INFO related functions =over =item * sk_X509_INFO_num Returns the number of values in a STACK_OF(X509_INFO) structure. my $rv = Net::SSLeay::sk_X509_INFO_num($sk_x509_info); # $sk_x509_info - value corresponding to openssl's STACK_OF(X509_INFO) structure # # returns: number of values in $sk_X509_info =item * sk_X509_INFO_value Returns the value of a STACK_OF(X509_INFO) structure at a given index. my $rv = Net::SSLeay::sk_X509_INFO_value($sk_x509_info, $index); # $sk_x509_info - value corresponding to openssl's STACK_OF(X509_INFO) structure # $index - index into the stack # # returns: value corresponding to openssl's X509_INFO structure at the given index =item * P_X509_INFO_get_x509 Returns the X509 structure stored in an X509_INFO structure. my $rv = Net::SSLeay::P_X509_INFO_get_x509($x509_info); # $x509_info - value corresponding to openssl's X509_INFO structure # # returns: value corresponding to openssl's X509 structure =back =head3 Low level API: X509_VERIFY_PARAM_* related functions =over =item * X509_VERIFY_PARAM_add0_policy Enables policy checking (it is disabled by default) and adds $policy to the acceptable policy set. my $rv = Net::SSLeay::X509_VERIFY_PARAM_add0_policy($param, $policy); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $policy - value corresponding to openssl's ASN1_OBJECT structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * X509_VERIFY_PARAM_add0_table ??? (more info needed) my $rv = Net::SSLeay::X509_VERIFY_PARAM_add0_table($param); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: 1 on success, 0 on failure =item * X509_VERIFY_PARAM_add1_host B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 Adds an additional reference identifier that can match the peer's certificate. my $rv = Net::SSLeay::X509_VERIFY_PARAM_add1_host($param, $name); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $name - (string) name to be set # # returns: 1 on success, 0 on failure See also OpenSSL docs, L and L for more information, including wildcard matching. Check openssl doc L =item * X509_VERIFY_PARAM_clear_flags Clears the flags $flags in param. my $rv = Net::SSLeay::X509_VERIFY_PARAM_clear_flags($param, $flags); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $flags - (unsigned long) flags to be set (bitmask) # # returns: 1 on success, 0 on failure For more details about $flags bitmask see L. Check openssl doc L =item * X509_VERIFY_PARAM_free Frees up the X509_VERIFY_PARAM structure. Net::SSLeay::X509_VERIFY_PARAM_free($param); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: no return value =item * X509_VERIFY_PARAM_get0_peername B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 Returns the DNS hostname or subject CommonName from the peer certificate that matched one of the reference identifiers. my $rv = Net::SSLeay::X509_VERIFY_PARAM_get0_peername($param); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: (string) name e.g. '*.example.com' or undef Check openssl doc L =item * X509_VERIFY_PARAM_get_depth Returns the current verification depth. my $rv = Net::SSLeay::X509_VERIFY_PARAM_get_depth($param); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: (ineger) depth Check openssl doc L =item * X509_VERIFY_PARAM_get_flags Returns the current verification flags. my $rv = Net::SSLeay::X509_VERIFY_PARAM_get_flags($param); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: (unsigned long) flags to be set (bitmask) For more details about returned flags bitmask see L. Check openssl doc L =item * X509_VERIFY_PARAM_set_flags my $rv = Net::SSLeay::X509_VERIFY_PARAM_set_flags($param, $flags); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $flags - (unsigned long) flags to be set (bitmask) # # returns: 1 on success, 0 on failure #to create $flags value use corresponding constants like $flags = Net::SSLeay::X509_V_FLAG_CRL_CHECK(); For more details about $flags bitmask, see the OpenSSL docs below. Check openssl doc L =item * X509_VERIFY_PARAM_inherit ??? (more info needed) my $rv = Net::SSLeay::X509_VERIFY_PARAM_inherit($to, $from); # $to - value corresponding to openssl's X509_VERIFY_PARAM structure # $from - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: 1 on success, 0 on failure =item * X509_VERIFY_PARAM_lookup Finds X509_VERIFY_PARAM by name. my $rv = Net::SSLeay::X509_VERIFY_PARAM_lookup($name); # $name - (string) name we want to find # # returns: value corresponding to openssl's X509_VERIFY_PARAM structure (0 on failure) =item * X509_VERIFY_PARAM_new Creates a new X509_VERIFY_PARAM structure. my $rv = Net::SSLeay::X509_VERIFY_PARAM_new(); # # returns: value corresponding to openssl's X509_VERIFY_PARAM structure (0 on failure) =item * X509_VERIFY_PARAM_set1 Sets the name of X509_VERIFY_PARAM structure $to to the same value as the name of X509_VERIFY_PARAM structure $from. my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1($to, $from); # $to - value corresponding to openssl's X509_VERIFY_PARAM structure # $from - value corresponding to openssl's X509_VERIFY_PARAM structure # # returns: 1 on success, 0 on failure =item * X509_VERIFY_PARAM_set1_email B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 Sets the expected RFC822 email address to email. my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_email($param, $email); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $email - (string) email to be set # # returns: 1 on success, 0 on failure Check openssl doc L =item * X509_VERIFY_PARAM_set1_host B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 Sets the expected DNS hostname to name clearing any previously specified host name or names. my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_host($param, $name); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $name - (string) name to be set # # returns: 1 on success, 0 on failure See also OpenSSL docs, L and L for more information, including wildcard matching. Check openssl doc L =item * X509_VERIFY_PARAM_set1_ip B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 Sets the expected IP address to ip. my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_ip($param, $ip); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $ip - (binary) 4 octet IPv4 or 16 octet IPv6 address # # returns: 1 on success, 0 on failure Check openssl doc L =item * X509_VERIFY_PARAM_set1_ip_asc B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 Sets the expected IP address to ipasc. my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_asc($param, $ipasc); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $ip - (string) IPv4 or IPv6 address # # returns: 1 on success, 0 on failure Check openssl doc L =item * X509_VERIFY_PARAM_set1_name Sets the name of X509_VERIFY_PARAM structure $param to $name. my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_name($param, $name); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $name - (string) name to be set # # returns: 1 on success, 0 on failure =item * X509_VERIFY_PARAM_set1_policies Enables policy checking (it is disabled by default) and sets the acceptable policy set to policies. Any existing policy set is cleared. The policies parameter can be 0 to clear an existing policy set. my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_policies($param, $policies); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $policies - value corresponding to openssl's STACK_OF(ASN1_OBJECT) structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * X509_VERIFY_PARAM_set_depth Sets the maximum verification depth to depth. That is the maximum number of untrusted CA certificates that can appear in a chain. Net::SSLeay::X509_VERIFY_PARAM_set_depth($param, $depth); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $depth - (integer) depth to be set # # returns: no return value Check openssl doc L =item * X509_VERIFY_PARAM_set_hostflags Net::SSLeay::X509_VERIFY_PARAM_set_hostflags($param, $flags); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $flags - (unsigned int) flags to be set (bitmask) # # returns: no return value See also OpenSSL docs, L and L for more information. The flags for controlling wildcard checks and other features are defined in OpenSSL docs. Check openssl doc L =item * X509_VERIFY_PARAM_set_purpose Sets the verification purpose in $param to $purpose. This determines the acceptable purpose of the certificate chain, for example SSL client or SSL server. my $rv = Net::SSLeay::X509_VERIFY_PARAM_set_purpose($param, $purpose); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $purpose - (integer) purpose identifier # # returns: 1 on success, 0 on failure For more details about $purpose identifier check L. Check openssl doc L =item * X509_VERIFY_PARAM_set_time Sets the verification time in $param to $t. Normally the current time is used. Net::SSLeay::X509_VERIFY_PARAM_set_time($param, $t); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $t - (time_t) time in seconds since 1.1.1970 # # returns: no return value Check openssl doc L =item * X509_VERIFY_PARAM_set_trust Sets the trust setting in $param to $trust. my $rv = Net::SSLeay::X509_VERIFY_PARAM_set_trust($param, $trust); # $param - value corresponding to openssl's X509_VERIFY_PARAM structure # $trust - (integer) trust identifier # # returns: 1 on success, 0 on failure For more details about $trust identifier check L. Check openssl doc L =item * X509_VERIFY_PARAM_table_cleanup ??? (more info needed) Net::SSLeay::X509_VERIFY_PARAM_table_cleanup(); # # returns: no return value =back =head3 Low level API: Cipher (EVP_CIPHER_*) related functions =over =item * EVP_get_cipherbyname B not available in Net-SSLeay-1.45 and before Returns an EVP_CIPHER structure when passed a cipher name. my $rv = Net::SSLeay::EVP_get_cipherbyname($name); # $name - (string) cipher name e.g. 'aes-128-cbc', 'camellia-256-ecb', 'des-ede', ... # # returns: value corresponding to openssl's EVP_CIPHER structure Check openssl doc L =back =head3 Low level API: Digest (EVP_MD_*) related functions =over =item * OpenSSL_add_all_digests B not available in Net-SSLeay-1.42 and before Net::SSLeay::OpenSSL_add_all_digests(); # no args, no return value http://www.openssl.org/docs/crypto/OpenSSL_add_all_algorithms.html =item * P_EVP_MD_list_all B not available in Net-SSLeay-1.42 and before; requires at least openssl-1.0.0 B Does not exactly correspond to any low level API function my $rv = Net::SSLeay::P_EVP_MD_list_all(); # # returns: arrayref - list of available digest names The returned digest names correspond to values expected by L. Note that some of the digests are available by default and some only after calling L. =item * EVP_get_digestbyname B not available in Net-SSLeay-1.42 and before my $rv = Net::SSLeay::EVP_get_digestbyname($name); # $name - string with digest name # # returns: value corresponding to openssl's EVP_MD structure The $name param can be: md2 md4 md5 mdc2 ripemd160 sha sha1 sha224 sha256 sha512 whirlpool Or better check the supported digests by calling L. =item * EVP_MD_type B not available in Net-SSLeay-1.42 and before my $rv = Net::SSLeay::EVP_MD_type($md); # $md - value corresponding to openssl's EVP_MD structure # # returns: the NID (integer) of the OBJECT IDENTIFIER representing the given message digest =item * EVP_MD_size B not available in Net-SSLeay-1.42 and before my $rv = Net::SSLeay::EVP_MD_size($md); # $md - value corresponding to openssl's EVP_MD structure # # returns: the size of the message digest in bytes (e.g. 20 for SHA1) =item * EVP_MD_CTX_md B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 Net::SSLeay::EVP_MD_CTX_md($ctx); # $ctx - value corresponding to openssl's EVP_MD_CTX structure # # returns: value corresponding to openssl's EVP_MD structure =item * EVP_MD_CTX_create B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 Allocates, initializes and returns a digest context. my $rv = Net::SSLeay::EVP_MD_CTX_create(); # # returns: value corresponding to openssl's EVP_MD_CTX structure The complete idea behind EVP_MD_CTX looks like this example: Net::SSLeay::OpenSSL_add_all_digests(); my $md = Net::SSLeay::EVP_get_digestbyname("sha1"); my $ctx = Net::SSLeay::EVP_MD_CTX_create(); Net::SSLeay::EVP_DigestInit($ctx, $md); while(my $chunk = get_piece_of_data()) { Net::SSLeay::EVP_DigestUpdate($ctx,$chunk); } my $result = Net::SSLeay::EVP_DigestFinal($ctx); Net::SSLeay::EVP_MD_CTX_destroy($ctx); print "digest=", unpack('H*', $result), "\n"; #print hex value =item * EVP_DigestInit_ex B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 Sets up digest context $ctx to use a digest $type from ENGINE $impl, $ctx must be initialized before calling this function, type will typically be supplied by a function such as L. If $impl is 0 then the default implementation of digest $type is used. my $rv = Net::SSLeay::EVP_DigestInit_ex($ctx, $type, $impl); # $ctx - value corresponding to openssl's EVP_MD_CTX structure # $type - value corresponding to openssl's EVP_MD structure # $impl - value corresponding to openssl's ENGINE structure # # returns: 1 for success and 0 for failure =item * EVP_DigestInit B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 Behaves in the same way as L except the passed context $ctx does not have to be initialized, and it always uses the default digest implementation. my $rv = Net::SSLeay::EVP_DigestInit($ctx, $type); # $ctx - value corresponding to openssl's EVP_MD_CTX structure # $type - value corresponding to openssl's EVP_MD structure # # returns: 1 for success and 0 for failure =item * EVP_MD_CTX_destroy B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 Cleans up digest context $ctx and frees up the space allocated to it, it should be called only on a context created using L. Net::SSLeay::EVP_MD_CTX_destroy($ctx); # $ctx - value corresponding to openssl's EVP_MD_CTX structure # # returns: no return value =item * EVP_DigestUpdate B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 my $rv = Net::SSLeay::EVP_DigestUpdate($ctx, $data); # $ctx - value corresponding to openssl's EVP_MD_CTX structure # $data - data to be hashed # # returns: 1 for success and 0 for failure =item * EVP_DigestFinal_ex B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 Retrieves the digest value from $ctx. After calling L no additional calls to L can be made, but L can be called to initialize a new digest operation. my $digest_value = Net::SSLeay::EVP_DigestFinal_ex($ctx); # $ctx - value corresponding to openssl's EVP_MD_CTX structure # # returns: hash value (binary) #to get printable (hex) value of digest use: print unpack('H*', $digest_value); =item * EVP_DigestFinal B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 Similar to L except the digest context ctx is automatically cleaned up. my $rv = Net::SSLeay::EVP_DigestFinal($ctx); # $ctx - value corresponding to openssl's EVP_MD_CTX structure # # returns: hash value (binary) #to get printable (hex) value of digest use: print unpack('H*', $digest_value); =item * MD2 B no supported by default in openssl-1.0.0 Computes MD2 from given $data (all data needs to be loaded into memory) my $digest = Net::SSLeay::MD2($data); print "digest(hexadecimal)=", unpack('H*', $digest); =item * MD4 Computes MD4 from given $data (all data needs to be loaded into memory) my $digest = Net::SSLeay::MD4($data); print "digest(hexadecimal)=", unpack('H*', $digest); =item * MD5 Computes MD5 from given $data (all data needs to be loaded into memory) my $digest = Net::SSLeay::MD5($data); print "digest(hexadecimal)=", unpack('H*', $digest); =item * RIPEMD160 Computes RIPEMD160 from given $data (all data needs to be loaded into memory) my $digest = Net::SSLeay::RIPEMD160($data); print "digest(hexadecimal)=", unpack('H*', $digest); =item * SHA1 B not available in Net-SSLeay-1.42 and before Computes SHA1 from given $data (all data needs to be loaded into memory) my $digest = Net::SSLeay::SHA1($data); print "digest(hexadecimal)=", unpack('H*', $digest); =item * SHA256 B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.8 Computes SHA256 from given $data (all data needs to be loaded into memory) my $digest = Net::SSLeay::SHA256($data); print "digest(hexadecimal)=", unpack('H*', $digest); =item * SHA512 B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.8 Computes SHA512 from given $data (all data needs to be loaded into memory) my $digest = Net::SSLeay::SHA512($data); print "digest(hexadecimal)=", unpack('H*', $digest); =item * EVP_Digest B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 Computes "any" digest from given $data (all data needs to be loaded into memory) my $md = Net::SSLeay::EVP_get_digestbyname("sha1"); #or any other algorithm my $digest = Net::SSLeay::EVP_Digest($data, $md); print "digest(hexadecimal)=", unpack('H*', $digest); =item * EVP_sha1 B not available in Net-SSLeay-1.42 and before my $md = Net::SSLeay::EVP_sha1(); # # returns: value corresponding to openssl's EVP_MD structure =item * EVP_sha256 B requires at least openssl-0.9.8 my $md = Net::SSLeay::EVP_sha256(); # # returns: value corresponding to openssl's EVP_MD structure =item * EVP_sha512 B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.8 my $md = Net::SSLeay::EVP_sha512(); # # returns: value corresponding to openssl's EVP_MD structure =item * EVP_add_digest my $rv = Net::SSLeay::EVP_add_digest($digest); # $digest - value corresponding to openssl's EVP_MD structure # # returns: 1 on success, 0 otherwise =back =head3 Low level API: CIPHER_* related functions =over =item * CIPHER_get_name B not available in Net-SSLeay-1.42 and before Returns name of the cipher used. my $rv = Net::SSLeay::CIPHER_description($cipher); # $cipher - value corresponding to openssl's SSL_CIPHER structure # # returns: (string) cipher name e.g. 'DHE-RSA-AES256-SHA' Check openssl doc L Example: my $ssl_cipher = Net::SSLeay::get_current_cipher($ssl); my $cipher_name = Net::SSLeay::CIPHER_get_name($ssl_cipher); =item * CIPHER_description Returns a textual description of the cipher used. ??? (does this function really work?) my $rv = Net::SSLeay::CIPHER_description($cipher, $buf, $size); # $cipher - value corresponding to openssl's SSL_CIPHER structure # $bufer - (string/buffer) ??? # $size - (integer) ??? # # returns: (string) cipher description e.g. 'DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1' Check openssl doc L =item * CIPHER_get_bits Returns the number of secret bits used for cipher. my $rv = Net::SSLeay::CIPHER_get_bits($c); # $c - value corresponding to openssl's SSL_CIPHER structure # # returns: (integert) number of secret bits, 0 on error Check openssl doc L =back =head3 Low level API: RSA_* related functions =over =item * RSA_generate_key Generates a key pair and returns it in a newly allocated RSA structure. The pseudo-random number generator must be seeded prior to calling RSA_generate_key. my $rv = Net::SSLeay::RSA_generate_key($bits, $e, $perl_cb, $perl_cb_arg); # $bits - (integer) modulus size in bits e.g. 512, 1024, 2048 # $e - (integer) public exponent, an odd number, typically 3, 17 or 65537 # $perl_cb - [optional] reference to perl callback function # $perl_cb_arg - [optional] data that will be passed to callback function when invoked # # returns: value corresponding to openssl's RSA structure (0 on failure) Check openssl doc L =item * RSA_free Frees the RSA structure and its components. The key is erased before the memory is returned to the system. Net::SSLeay::RSA_free($r); # $r - value corresponding to openssl's RSA structure # # returns: no return value Check openssl doc L =item * RSA_get_key_parameters Returns a list of pointers to BIGNUMs representing the parameters of the key in this order: (n, e, d, p, q, dmp1, dmq1, iqmp) Caution: returned list consists of SV pointers to BIGNUMs, which would need to be blessed as Crypt::OpenSSL::Bignum for further use my (@params) = RSA_get_key_parameters($r); =back =head3 Low level API: BIO_* related functions =over =item * BIO_eof Returns 1 if the BIO has read EOF, the precise meaning of 'EOF' varies according to the BIO type. my $rv = Net::SSLeay::BIO_eof($s); # $s - value corresponding to openssl's BIO structure # # returns: 1 if EOF has been reached 0 otherwise Check openssl doc L =item * BIO_f_ssl Returns the SSL BIO method. This is a filter BIO which is a wrapper round the OpenSSL SSL routines adding a BIO 'flavour' to SSL I/O. my $rv = Net::SSLeay::BIO_f_ssl(); # # returns: value corresponding to openssl's BIO_METHOD structure (0 on failure) Check openssl doc L =item * BIO_free Frees up a single BIO. my $rv = Net::SSLeay::BIO_free($bio;); # $bio; - value corresponding to openssl's BIO structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * BIO_new Returns a new BIO using method $type my $rv = Net::SSLeay::BIO_new($type); # $type - value corresponding to openssl's BIO_METHOD structure # # returns: value corresponding to openssl's BIO structure (0 on failure) Check openssl doc L =item * BIO_new_buffer_ssl_connect Creates a new BIO chain consisting of a buffering BIO, an SSL BIO (using ctx) and a connect BIO. my $rv = Net::SSLeay::BIO_new_buffer_ssl_connect($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: value corresponding to openssl's BIO structure (0 on failure) Check openssl doc L =item * BIO_new_file Creates a new file BIO with mode $mode the meaning of mode is the same as the stdio function fopen(). The BIO_CLOSE flag is set on the returned BIO. my $rv = Net::SSLeay::BIO_new_file($filename, $mode); # $filename - (string) filename # $mode - (string) opening mode (as mode by stdio function fopen) # # returns: value corresponding to openssl's BIO structure (0 on failure) Check openssl doc L =item * BIO_new_ssl Allocates an SSL BIO using SSL_CTX ctx and using client mode if client is non zero. my $rv = Net::SSLeay::BIO_new_ssl($ctx, $client); # $ctx - value corresponding to openssl's SSL_CTX structure # $client - (integer) 0 or 1 - indicates ssl client mode # # returns: value corresponding to openssl's BIO structure (0 on failure) Check openssl doc L =item * BIO_new_ssl_connect Creates a new BIO chain consisting of an SSL BIO (using ctx) followed by a connect BIO. my $rv = Net::SSLeay::BIO_new_ssl_connect($ctx); # $ctx - value corresponding to openssl's SSL_CTX structure # # returns: value corresponding to openssl's BIO structure (0 on failure) Check openssl doc L =item * BIO_pending Return the number of pending characters in the BIOs read buffers. my $rv = Net::SSLeay::BIO_pending($s); # $s - value corresponding to openssl's BIO structure # # returns: the amount of pending data Check openssl doc L =item * BIO_wpending Return the number of pending characters in the BIOs write buffers. my $rv = Net::SSLeay::BIO_wpending($s); # $s - value corresponding to openssl's BIO structure # # returns: the amount of pending data Check openssl doc L =item * BIO_read Read the underlying descriptor. Net::SSLeay::BIO_read($s, $max); # $s - value corresponding to openssl's BIO structure # $max - [optional] max. bytes to read (if not specified, the value 32768 is used) # # returns: data Check openssl doc L =item * BIO_write Attempts to write data from $buffer to BIO $b. my $rv = Net::SSLeay::BIO_write($b, $buffer); # $b - value corresponding to openssl's BIO structure # $buffer - data # # returns: amount of data successfully written # or that no data was successfully read or written if the result is 0 or -1 # or -2 when the operation is not implemented in the specific BIO type Check openssl doc L =item * BIO_s_mem Return the memory BIO method function. my $rv = Net::SSLeay::BIO_s_mem(); # # returns: value corresponding to openssl's BIO_METHOD structure (0 on failure) Check openssl doc L =item * BIO_ssl_copy_session_id Copies an SSL session id between BIO chains from and to. It does this by locating the SSL BIOs in each chain and calling SSL_copy_session_id() on the internal SSL pointer. my $rv = Net::SSLeay::BIO_ssl_copy_session_id($to, $from); # $to - value corresponding to openssl's BIO structure # $from - value corresponding to openssl's BIO structure # # returns: 1 on success, 0 on failure Check openssl doc L =item * BIO_ssl_shutdown Closes down an SSL connection on BIO chain bio. It does this by locating the SSL BIO in the chain and calling SSL_shutdown() on its internal SSL pointer. Net::SSLeay::BIO_ssl_shutdown($ssl_bio); # $ssl_bio - value corresponding to openssl's BIO structure # # returns: no return value Check openssl doc L =back =head3 Low level API: Server side Server Name Indication (SNI) support =over =item * set_tlsext_host_name TBA =item * get_servername TBA =item * get_servername_type TBA =item * CTX_set_tlsext_servername_callback B requires at least OpenSSL 0.9.8f This function is used in a server to support Server side Server Name Indication (SNI). Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, $code) # $ctx - SSL context # $code - reference to a subroutine that will be called when a new connection is being initiated # # returns: no return value On the client side: use set_tlsext_host_name($ssl, $servername) before initiating the SSL connection. On the server side: Set up an additional SSL_CTX() for each different certificate; Add a servername callback to each SSL_CTX() using CTX_set_tlsext_servername_callback(); The callback function is required to retrieve the client-supplied servername with get_servername(ssl). Figure out the right SSL_CTX to go with that host name, then switch the SSL object to that SSL_CTX with set_SSL_CTX(). Example: # set callback Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, sub { my $ssl = shift; my $h = Net::SSLeay::get_servername($ssl); Net::SSLeay::set_SSL_CTX($ssl, $hostnames{$h}->{ctx}) if exists $hostnames{$h}; } ); More complete example: # ... initialize Net::SSLeay my %hostnames = ( 'sni1' => { cert=>'sni1.pem', key=>'sni1.key' }, 'sni2' => { cert=>'sni2.pem', key=>'sni2.key' }, ); # create a new context for each certificate/key pair for my $name (keys %hostnames) { $hostnames{$name}->{ctx} = Net::SSLeay::CTX_new or die; Net::SSLeay::CTX_set_cipher_list($hostnames{$name}->{ctx}, 'ALL'); Net::SSLeay::set_cert_and_key($hostnames{$name}->{ctx}, $hostnames{$name}->{cert}, $hostnames{$name}->{key}) or die; } # create default context my $ctx = Net::SSLeay::CTX_new or die; Net::SSLeay::CTX_set_cipher_list($ctx, 'ALL'); Net::SSLeay::set_cert_and_key($ctx, 'cert.pem','key.pem') or die; # set callback Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, sub { my $ssl = shift; my $h = Net::SSLeay::get_servername($ssl); Net::SSLeay::set_SSL_CTX($ssl, $hostnames{$h}->{ctx}) if exists $hostnames{$h}; } ); # ... later $s = Net::SSLeay::new($ctx); Net::SSLeay::set_fd($s, fileno($accepted_socket)); Net::SSLeay::accept($s); =back =head3 Low level API: NPN (next protocol negotiation) related functions NPN is being replaced with ALPN, a more recent TLS extension for application protocol negotiation that's in process of being adopted by IETF. Please look below for APLN API description. Simple approach for using NPN support looks like this: ### client side use Net::SSLeay; use IO::Socket::INET; Net::SSLeay::initialize(); my $sock = IO::Socket::INET->new(PeerAddr=>'encrypted.google.com:443') or die; my $ctx = Net::SSLeay::CTX_tlsv1_new() or die; Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); Net::SSLeay::CTX_set_next_proto_select_cb($ctx, ['http1.1','spdy/2']); my $ssl = Net::SSLeay::new($ctx) or die; Net::SSLeay::set_fd($ssl, fileno($sock)) or die; Net::SSLeay::connect($ssl); warn "client:negotiated=",Net::SSLeay::P_next_proto_negotiated($ssl), "\n"; warn "client:last_status=", Net::SSLeay::P_next_proto_last_status($ssl), "\n"; ### server side use Net::SSLeay; use IO::Socket::INET; Net::SSLeay::initialize(); my $ctx = Net::SSLeay::CTX_tlsv1_new() or die; Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); Net::SSLeay::set_cert_and_key($ctx, "cert.pem", "key.pem"); Net::SSLeay::CTX_set_next_protos_advertised_cb($ctx, ['spdy/2','http1.1']); my $sock = IO::Socket::INET->new(LocalAddr=>'localhost', LocalPort=>5443, Proto=>'tcp', Listen=>20) or die; while (1) { my $ssl = Net::SSLeay::new($ctx); warn("server:waiting for incoming connection...\n"); my $fd = $sock->accept(); Net::SSLeay::set_fd($ssl, $fd->fileno); Net::SSLeay::accept($ssl); warn "server:negotiated=",Net::SSLeay::P_next_proto_negotiated($ssl),"\n"; my $got = Net::SSLeay::read($ssl); Net::SSLeay::ssl_write_all($ssl, "length=".length($got)); Net::SSLeay::free($ssl); $fd->close(); } # check with: openssl s_client -connect localhost:5443 -nextprotoneg http/1.1,spdy/2 Please note that the selection (negotiation) is performed by client side, the server side simply advertise the list of supported protocols. Advanced approach allows you to implement your own negotiation algorithm. #see below documentation for: Net::SSleay::CTX_set_next_proto_select_cb($ctx, $perl_callback_function, $callback_data); Net::SSleay::CTX_set_next_protos_advertised_cb($ctx, $perl_callback_function, $callback_data); Detection of NPN support (works even in older Net::SSLeay versions): use Net::SSLeay; if (exists &Net::SSLeay::P_next_proto_negotiated) { # do NPN stuff } =over =item * CTX_set_next_proto_select_cb B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.1 B You need CTX_set_next_proto_select_cb on B of SSL connection. Simple usage - in this case a "common" negotiation algorithm (as implemented by openssl's function SSL_select_next_proto) is used. $rv = Net::SSleay::CTX_set_next_proto_select_cb($ctx, $arrayref); # $ctx - value corresponding to openssl's SSL_CTX structure # $arrayref - list of accepted protocols - e.g. ['http1.0', 'http1.1'] # # returns: 0 on success, 1 on failure Advanced usage (you probably do not need this): $rv = Net::SSleay::CTX_set_next_proto_select_cb($ctx, $perl_callback_function, $callback_data); # $ctx - value corresponding to openssl's SSL_CTX structure # $perl_callback_function - reference to perl function # $callback_data - [optional] data to passed to callback function when invoked # # returns: 0 on success, 1 on failure # where callback function looks like sub npn_advertised_cb_invoke { my ($ssl, $arrayref_proto_list_advertised_by_server, $callback_data) = @_; my $status; # ... $status = 1; #status can be: # 0 - OPENSSL_NPN_UNSUPPORTED # 1 - OPENSSL_NPN_NEGOTIATED # 2 - OPENSSL_NPN_NO_OVERLAP return $status, ['http1.1','spdy/2']; # the callback has to return 2 values } To undefine/clear this callback use: Net::SSleay::CTX_set_next_proto_select_cb($ctx, undef); =item * CTX_set_next_protos_advertised_cb B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.1 B You need CTX_set_next_proto_select_cb on B of SSL connection. Simple usage: $rv = Net::SSleay::CTX_set_next_protos_advertised_cb($ctx, $arrayref); # $ctx - value corresponding to openssl's SSL_CTX structure # $arrayref - list of advertised protocols - e.g. ['http1.0', 'http1.1'] # # returns: 0 on success, 1 on failure Advanced usage (you probably do not need this): $rv = Net::SSleay::CTX_set_next_protos_advertised_cb($ctx, $perl_callback_function, $callback_data); # $ctx - value corresponding to openssl's SSL_CTX structure # $perl_callback_function - reference to perl function # $callback_data - [optional] data to passed to callback function when invoked # # returns: 0 on success, 1 on failure # where callback function looks like sub npn_advertised_cb_invoke { my ($ssl, $callback_data) = @_; # ... return ['http1.1','spdy/2']; # the callback has to return arrayref } To undefine/clear this callback use: Net::SSleay::CTX_set_next_protos_advertised_cb($ctx, undef); =item * P_next_proto_negotiated B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.1 Returns the name of negotiated protocol for given SSL connection $ssl. $rv = Net::SSLeay::P_next_proto_negotiated($ssl) # $ssl - value corresponding to openssl's SSL structure # # returns: (string) negotiated protocol name (or undef if no negotiation was done or failed with fatal error) =item * P_next_proto_last_status B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.1 Returns the result of the last negotiation for given SSL connection $ssl. $rv = Net::SSLeay::P_next_proto_last_status($ssl) # $ssl - value corresponding to openssl's SSL structure # # returns: (integer) negotiation status # 0 - OPENSSL_NPN_UNSUPPORTED # 1 - OPENSSL_NPN_NEGOTIATED # 2 - OPENSSL_NPN_NO_OVERLAP =back =head3 Low level API: ALPN (application layer protocol negotiation) related functions Application protocol can be negotiated via two different mechanisms employing two different TLS extensions: NPN (obsolete) and ALPN (recommended). The API is rather similar, with slight differences reflecting protocol specifics. In particular, with ALPN the protocol negotiation takes place on server, while with NPN the client implements the protocol negotiation logic. With ALPN, the most basic implementation looks like this: ### client side use Net::SSLeay; use IO::Socket::INET; Net::SSLeay::initialize(); my $sock = IO::Socket::INET->new(PeerAddr=>'encrypted.google.com:443') or die; my $ctx = Net::SSLeay::CTX_tlsv1_new() or die; Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); Net::SSLeay::CTX_set_alpn_protos($ctx, ['http/1.1', 'http/2.0', 'spdy/3]); my $ssl = Net::SSLeay::new($ctx) or die; Net::SSLeay::set_fd($ssl, fileno($sock)) or die; Net::SSLeay::connect($ssl); warn "client:selected=",Net::SSLeay::P_alpn_selected($ssl), "\n"; ### server side use Net::SSLeay; use IO::Socket::INET; Net::SSLeay::initialize(); my $ctx = Net::SSLeay::CTX_tlsv1_new() or die; Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); Net::SSLeay::set_cert_and_key($ctx, "cert.pem", "key.pem"); Net::SSLeay::CTX_set_alpn_select_cb($ctx, ['http/1.1', 'http/2.0', 'spdy/3]); my $sock = IO::Socket::INET->new(LocalAddr=>'localhost', LocalPort=>5443, Proto=>'tcp', Listen=>20) or die; while (1) { my $ssl = Net::SSLeay::new($ctx); warn("server:waiting for incoming connection...\n"); my $fd = $sock->accept(); Net::SSLeay::set_fd($ssl, $fd->fileno); Net::SSLeay::accept($ssl); warn "server:selected=",Net::SSLeay::P_alpn_selected($ssl),"\n"; my $got = Net::SSLeay::read($ssl); Net::SSLeay::ssl_write_all($ssl, "length=".length($got)); Net::SSLeay::free($ssl); $fd->close(); } # check with: openssl s_client -connect localhost:5443 -alpn spdy/3,http/1.1 Advanced approach allows you to implement your own negotiation algorithm. #see below documentation for: Net::SSleay::CTX_set_alpn_select_cb($ctx, $perl_callback_function, $callback_data); Detection of ALPN support (works even in older Net::SSLeay versions): use Net::SSLeay; if (exists &Net::SSLeay::P_alpn_selected) { # do ALPN stuff } =over =item * CTX_set_alpn_select_cb B not available in Net-SSLeay-1.55 and before; requires at least openssl-1.0.2 B You need CTX_set_alpn_select_cb on B of TLS connection. Simple usage - in this case a "common" negotiation algorithm (as implemented by openssl's function SSL_select_next_proto) is used. $rv = Net::SSleay::CTX_set_alpn_select_cb($ctx, $arrayref); # $ctx - value corresponding to openssl's SSL_CTX structure # $arrayref - list of accepted protocols - e.g. ['http/2.0', 'http/1.1', 'spdy/3'] # # returns: 0 on success, 1 on failure Advanced usage (you probably do not need this): $rv = Net::SSleay::CTX_set_alpn_select_cb($ctx, $perl_callback_function, $callback_data); # $ctx - value corresponding to openssl's SSL_CTX structure # $perl_callback_function - reference to perl function # $callback_data - [optional] data to passed to callback function when invoked # # returns: 0 on success, 1 on failure # where callback function looks like sub alpn_select_cb_invoke { my ($ssl, $arrayref_proto_list_advertised_by_client, $callback_data) = @_; # ... if ($negotiated) { return 'http/2.0'; } else { return undef; } } To undefine/clear this callback use: Net::SSleay::CTX_set_alpn_select_cb($ctx, undef); =item * set_alpn_protos B not available in Net-SSLeay-1.55 and before; requires at least openssl-1.0.2 B You need set_alpn_protos on B of TLS connection. This adds list of supported application layer protocols to ClientHello message sent by a client. It advertises the enumeration of supported protocols: Net::SSLeay::set_alpn_protos($ssl, ['http/1.1', 'http/2.0', 'spdy/3]); # returns 0 on success =item * CTX_set_alpn_protos B not available in Net-SSLeay-1.55 and before; requires at least openssl-1.0.2 B You need CTX_set_alpn_protos on B of TLS connection. This adds list of supported application layer protocols to ClientHello message sent by a client. It advertises the enumeration of supported protocols: Net::SSLeay::CTX_set_alpn_protos($ctx, ['http/1.1', 'http/2.0', 'spdy/3]); # returns 0 on success =item * P_alpn_selected B not available in Net-SSLeay-1.55 and before; requires at least openssl-1.0.2 Returns the name of negotiated protocol for given TLS connection $ssl. $rv = Net::SSLeay::P_alpn_selected($ssl) # $ssl - value corresponding to openssl's SSL structure # # returns: (string) negotiated protocol name (or undef if no negotiation was done or failed with fatal error) =back =head3 Low level API: DANE Support OpenSSL version 1.0.2 adds preliminary support RFC6698 Domain Authentication of Named Entities (DANE) Transport Layer Association within OpenSSL =over =item * SSL_get_tlsa_record_byname B DELETED from net-ssleay, since it is not supported by OpenSSL In order to facilitate DANE there is additional interface, SSL_get_tlsa_record_byname, accepting hostname, port and socket type that returns packed TLSA record. In order to make it even easier there is additional SSL_ctrl function that calls SSL_get_tlsa_record_byname for you. Latter is recommended for programmers that wish to maintain broader binary compatibility, e.g. make application work with both 1.0.2 and prior version (in which case call to SSL_ctrl with new code returning error would have to be ignored when running with prior version). Net::SSLeay::get_tlsa_record_byname($name, $port, $type); =back =head3 Low level API: Other functions =over =item * COMP_add_compression_method Adds the compression method cm with the identifier id to the list of available compression methods. This list is globally maintained for all SSL operations within this application. It cannot be set for specific SSL_CTX or SSL objects. my $rv = Net::SSLeay::COMP_add_compression_method($id, $cm); # $id - (integer) compression method id # 0 to 63: methods defined by the IETF # 64 to 192: external party methods assigned by IANA # 193 to 255: reserved for private use # # $cm - value corresponding to openssl's COMP_METHOD structure # # returns: 0 on success, 1 on failure (check the error queue to find out the reason) Check openssl doc L =item * DH_free Frees the DH structure and its components. The values are erased before the memory is returned to the system. Net::SSLeay::DH_free($dh); # $dh - value corresponding to openssl's DH structure # # returns: no return value Check openssl doc L =item * FIPS_mode_set Enable or disable FIPS mode in a FIPS capable OpenSSL. Net::SSLeay:: FIPS_mode_set($enable); # $enable - (integer) 1 to enable, 0 to disable =back =head3 Low level API: EC related functions =over =item * CTX_set_tmp_ecdh TBA =item * EC_KEY_free TBA =item * EC_KEY_new_by_curve_name TBA =item * EC_KEY_generate_key Generates a EC key and returns it in a newly allocated EC_KEY structure. The EC key then can be used to create a PKEY which can be used in calls like X509_set_pubkey. my $key = Net::SSLeay::EVP_PKEY_new(); my $ec = Net::SSLeay::EC_KEY_generate_key($curve); Net::SSLeay::EVP_PKEY_assign_EC_KEY($key,$ec); # $curve - curve name like 'secp521r1' or the matching Id (integer) of the curve # # returns: value corresponding to openssl's EC_KEY structure (0 on failure) This function has no equivalent in OpenSSL but combines multiple OpenSSL functions for an easier interface. =item * CTX_set_ecdh_auto, set_ecdh_auto These functions enable or disable the automatic curve selection on the server side by calling SSL_CTX_set_ecdh_auto or SSL_set_ecdh_auto respectively. If enabled the highest preference curve is automatically used for ECDH temporary keys used during key exchange. This function is no longer available for OpenSSL 1.1.0 or higher. Net::SSLeay::CTX_set_ecdh_auto($ctx,1); Net::SSLeay::set_ecdh_auto($ssl,1); =item * CTX_set1_curves_list, set1_curves_list These functions set the supported curves (in order of preference) by calling SSL_CTX_set1_curves_list or SSL_set1_curves_list respectively. For a TLS client these curves are offered to the server in the supported curves extension while on the server side these are used to determine the shared curve. These functions are only available since OpenSSL 1.1.0. Net::SSLeay::CTX_set1_curves_list($ctx,"P-521:P-384:P-256"); Net::SSLeay::set1_curves_list($ssl,"P-521:P-384:P-256"); =item * CTX_set1_groups_list, set1_groups_list These functions set the supported groups (in order of preference) by calling SSL_CTX_set1_groups_list or SSL_set1_groups_list respectively. This is practically the same as CTX_set1_curves_list and set1_curves_list except that all DH groups can be given as supported by TLS 1.3. These functions are only available since OpenSSL 1.1.1. Net::SSLeay::CTX_set1_groups_list($ctx,"P-521:P-384:P-256"); Net::SSLeay::set1_groups_list($ssl,"P-521:P-384:P-256"); =back =head2 Constants There are many openssl constants available in L. You can use them like this: use Net::SSLeay; print &Net::SSLeay::NID_commonName; #or print Net::SSLeay::NID_commonName(); Or you can import them and use: use Net::SSLeay qw/NID_commonName/; print &NID_commonName; #or print NID_commonName(); #or print NID_commonName; The constants names are derived from openssl constants, however constants starting with C prefix have name with C part stripped - e.g. openssl's constant C is available as C The list of all available constant names: =for comment the next part is the output of: perl helper_script/regen_openssl_constants.pl -gen-pod ASN1_STRFLGS_ESC_CTRL NID_netscape R_UNKNOWN_REMOTE_ERROR_TYPE ASN1_STRFLGS_ESC_MSB NID_netscape_base_url R_UNKNOWN_STATE ASN1_STRFLGS_ESC_QUOTE NID_netscape_ca_policy_url R_X509_LIB ASN1_STRFLGS_RFC2253 NID_netscape_ca_revocation_url SENT_SHUTDOWN CB_ACCEPT_EXIT NID_netscape_cert_extension SESSION_ASN1_VERSION CB_ACCEPT_LOOP NID_netscape_cert_sequence SESS_CACHE_BOTH CB_ALERT NID_netscape_cert_type SESS_CACHE_CLIENT CB_CONNECT_EXIT NID_netscape_comment SESS_CACHE_NO_AUTO_CLEAR CB_CONNECT_LOOP NID_netscape_data_type SESS_CACHE_NO_INTERNAL CB_EXIT NID_netscape_renewal_url SESS_CACHE_NO_INTERNAL_LOOKUP CB_HANDSHAKE_DONE NID_netscape_revocation_url SESS_CACHE_NO_INTERNAL_STORE CB_HANDSHAKE_START NID_netscape_ssl_server_name SESS_CACHE_OFF CB_LOOP NID_ns_sgc SESS_CACHE_SERVER CB_READ NID_organizationName SSL3_VERSION CB_READ_ALERT NID_organizationalUnitName SSLEAY_BUILT_ON CB_WRITE NID_pbeWithMD2AndDES_CBC SSLEAY_CFLAGS CB_WRITE_ALERT NID_pbeWithMD2AndRC2_CBC SSLEAY_DIR ERROR_NONE NID_pbeWithMD5AndCast5_CBC SSLEAY_PLATFORM ERROR_SSL NID_pbeWithMD5AndDES_CBC SSLEAY_VERSION ERROR_SYSCALL NID_pbeWithMD5AndRC2_CBC ST_ACCEPT ERROR_WANT_ACCEPT NID_pbeWithSHA1AndDES_CBC ST_BEFORE ERROR_WANT_CONNECT NID_pbeWithSHA1AndRC2_CBC ST_CONNECT ERROR_WANT_READ NID_pbe_WithSHA1And128BitRC2_CBC ST_INIT ERROR_WANT_WRITE NID_pbe_WithSHA1And128BitRC4 ST_OK ERROR_WANT_X509_LOOKUP NID_pbe_WithSHA1And2_Key_TripleDES_CBC ST_READ_BODY ERROR_ZERO_RETURN NID_pbe_WithSHA1And3_Key_TripleDES_CBC ST_READ_HEADER EVP_PKS_DSA NID_pbe_WithSHA1And40BitRC2_CBC TLS1_1_VERSION EVP_PKS_EC NID_pbe_WithSHA1And40BitRC4 TLS1_2_VERSION EVP_PKS_RSA NID_pbes2 TLS1_3_VERSION EVP_PKT_ENC NID_pbmac1 TLS1_VERSION EVP_PKT_EXCH NID_pkcs TLSEXT_STATUSTYPE_ocsp EVP_PKT_EXP NID_pkcs3 VERIFY_CLIENT_ONCE EVP_PKT_SIGN NID_pkcs7 VERIFY_FAIL_IF_NO_PEER_CERT EVP_PK_DH NID_pkcs7_data VERIFY_NONE EVP_PK_DSA NID_pkcs7_digest VERIFY_PEER EVP_PK_EC NID_pkcs7_encrypted VERIFY_POST_HANDSHAKE EVP_PK_RSA NID_pkcs7_enveloped V_OCSP_CERTSTATUS_GOOD FILETYPE_ASN1 NID_pkcs7_signed V_OCSP_CERTSTATUS_REVOKED FILETYPE_PEM NID_pkcs7_signedAndEnveloped V_OCSP_CERTSTATUS_UNKNOWN F_CLIENT_CERTIFICATE NID_pkcs8ShroudedKeyBag WRITING F_CLIENT_HELLO NID_pkcs9 X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT F_CLIENT_MASTER_KEY NID_pkcs9_challengePassword X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS F_D2I_SSL_SESSION NID_pkcs9_contentType X509_CHECK_FLAG_NEVER_CHECK_SUBJECT F_GET_CLIENT_FINISHED NID_pkcs9_countersignature X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS F_GET_CLIENT_HELLO NID_pkcs9_emailAddress X509_CHECK_FLAG_NO_WILDCARDS F_GET_CLIENT_MASTER_KEY NID_pkcs9_extCertAttributes X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS F_GET_SERVER_FINISHED NID_pkcs9_messageDigest X509_FILETYPE_ASN1 F_GET_SERVER_HELLO NID_pkcs9_signingTime X509_FILETYPE_DEFAULT F_GET_SERVER_VERIFY NID_pkcs9_unstructuredAddress X509_FILETYPE_PEM F_I2D_SSL_SESSION NID_pkcs9_unstructuredName X509_LOOKUP F_READ_N NID_private_key_usage_period X509_PURPOSE_ANY F_REQUEST_CERTIFICATE NID_rc2_40_cbc X509_PURPOSE_CRL_SIGN F_SERVER_HELLO NID_rc2_64_cbc X509_PURPOSE_NS_SSL_SERVER F_SSL_CERT_NEW NID_rc2_cbc X509_PURPOSE_OCSP_HELPER F_SSL_GET_NEW_SESSION NID_rc2_cfb64 X509_PURPOSE_SMIME_ENCRYPT F_SSL_NEW NID_rc2_ecb X509_PURPOSE_SMIME_SIGN F_SSL_READ NID_rc2_ofb64 X509_PURPOSE_SSL_CLIENT F_SSL_RSA_PRIVATE_DECRYPT NID_rc4 X509_PURPOSE_SSL_SERVER F_SSL_RSA_PUBLIC_ENCRYPT NID_rc4_40 X509_PURPOSE_TIMESTAMP_SIGN F_SSL_SESSION_NEW NID_rc5_cbc X509_TRUST_COMPAT F_SSL_SESSION_PRINT_FP NID_rc5_cfb64 X509_TRUST_EMAIL F_SSL_SET_FD NID_rc5_ecb X509_TRUST_OBJECT_SIGN F_SSL_SET_RFD NID_rc5_ofb64 X509_TRUST_OCSP_REQUEST F_SSL_SET_WFD NID_ripemd160 X509_TRUST_OCSP_SIGN F_SSL_USE_CERTIFICATE NID_ripemd160WithRSA X509_TRUST_SSL_CLIENT F_SSL_USE_CERTIFICATE_ASN1 NID_rle_compression X509_TRUST_SSL_SERVER F_SSL_USE_CERTIFICATE_FILE NID_rsa X509_TRUST_TSA F_SSL_USE_PRIVATEKEY NID_rsaEncryption X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH F_SSL_USE_PRIVATEKEY_ASN1 NID_rsadsi X509_V_ERR_AKID_SKID_MISMATCH F_SSL_USE_PRIVATEKEY_FILE NID_safeContentsBag X509_V_ERR_APPLICATION_VERIFICATION F_SSL_USE_RSAPRIVATEKEY NID_sdsiCertificate X509_V_ERR_CA_KEY_TOO_SMALL F_SSL_USE_RSAPRIVATEKEY_ASN1 NID_secretBag X509_V_ERR_CA_MD_TOO_WEAK F_SSL_USE_RSAPRIVATEKEY_FILE NID_serialNumber X509_V_ERR_CERT_CHAIN_TOO_LONG F_WRITE_PENDING NID_server_auth X509_V_ERR_CERT_HAS_EXPIRED GEN_DIRNAME NID_sha X509_V_ERR_CERT_NOT_YET_VALID GEN_DNS NID_sha1 X509_V_ERR_CERT_REJECTED GEN_EDIPARTY NID_sha1WithRSA X509_V_ERR_CERT_REVOKED GEN_EMAIL NID_sha1WithRSAEncryption X509_V_ERR_CERT_SIGNATURE_FAILURE GEN_IPADD NID_shaWithRSAEncryption X509_V_ERR_CERT_UNTRUSTED GEN_OTHERNAME NID_stateOrProvinceName X509_V_ERR_CRL_HAS_EXPIRED GEN_RID NID_subject_alt_name X509_V_ERR_CRL_NOT_YET_VALID GEN_URI NID_subject_key_identifier X509_V_ERR_CRL_PATH_VALIDATION_ERROR GEN_X400 NID_surname X509_V_ERR_CRL_SIGNATURE_FAILURE LIBRESSL_VERSION_NUMBER NID_sxnet X509_V_ERR_DANE_NO_MATCH MBSTRING_ASC NID_time_stamp X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT MBSTRING_BMP NID_title X509_V_ERR_DIFFERENT_CRL_SCOPE MBSTRING_FLAG NID_undef X509_V_ERR_EE_KEY_TOO_SMALL MBSTRING_UNIV NID_uniqueIdentifier X509_V_ERR_EMAIL_MISMATCH MBSTRING_UTF8 NID_x509Certificate X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD MIN_RSA_MODULUS_LENGTH_IN_BYTES NID_x509Crl X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD MODE_ACCEPT_MOVING_WRITE_BUFFER NID_zlib_compression X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD MODE_AUTO_RETRY NOTHING X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD MODE_ENABLE_PARTIAL_WRITE OCSP_RESPONSE_STATUS_INTERNALERROR X509_V_ERR_EXCLUDED_VIOLATION MODE_RELEASE_BUFFERS OCSP_RESPONSE_STATUS_MALFORMEDREQUEST X509_V_ERR_HOSTNAME_MISMATCH NID_OCSP_sign OCSP_RESPONSE_STATUS_SIGREQUIRED X509_V_ERR_INVALID_CA NID_SMIMECapabilities OCSP_RESPONSE_STATUS_SUCCESSFUL X509_V_ERR_INVALID_CALL NID_X500 OCSP_RESPONSE_STATUS_TRYLATER X509_V_ERR_INVALID_EXTENSION NID_X509 OCSP_RESPONSE_STATUS_UNAUTHORIZED X509_V_ERR_INVALID_NON_CA NID_ad_OCSP OPENSSL_BUILT_ON X509_V_ERR_INVALID_POLICY_EXTENSION NID_ad_ca_issuers OPENSSL_CFLAGS X509_V_ERR_INVALID_PURPOSE NID_algorithm OPENSSL_DIR X509_V_ERR_IP_ADDRESS_MISMATCH NID_authority_key_identifier OPENSSL_ENGINES_DIR X509_V_ERR_KEYUSAGE_NO_CERTSIGN NID_basic_constraints OPENSSL_PLATFORM X509_V_ERR_KEYUSAGE_NO_CRL_SIGN NID_bf_cbc OPENSSL_VERSION X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE NID_bf_cfb64 OPENSSL_VERSION_NUMBER X509_V_ERR_NO_EXPLICIT_POLICY NID_bf_ecb OP_ALL X509_V_ERR_NO_VALID_SCTS NID_bf_ofb64 OP_ALLOW_NO_DHE_KEX X509_V_ERR_OCSP_CERT_UNKNOWN NID_cast5_cbc OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION X509_V_ERR_OCSP_VERIFY_FAILED NID_cast5_cfb64 OP_CIPHER_SERVER_PREFERENCE X509_V_ERR_OCSP_VERIFY_NEEDED NID_cast5_ecb OP_CISCO_ANYCONNECT X509_V_ERR_OUT_OF_MEM NID_cast5_ofb64 OP_COOKIE_EXCHANGE X509_V_ERR_PATH_LENGTH_EXCEEDED NID_certBag OP_CRYPTOPRO_TLSEXT_BUG X509_V_ERR_PATH_LOOP NID_certificate_policies OP_DONT_INSERT_EMPTY_FRAGMENTS X509_V_ERR_PERMITTED_VIOLATION NID_client_auth OP_ENABLE_MIDDLEBOX_COMPAT X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED NID_code_sign OP_EPHEMERAL_RSA X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED NID_commonName OP_LEGACY_SERVER_CONNECT X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION NID_countryName OP_MICROSOFT_BIG_SSLV3_BUFFER X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN NID_crlBag OP_MICROSOFT_SESS_ID_BUG X509_V_ERR_STORE_LOOKUP NID_crl_distribution_points OP_MSIE_SSLV2_RSA_PADDING X509_V_ERR_SUBJECT_ISSUER_MISMATCH NID_crl_number OP_NETSCAPE_CA_DN_BUG X509_V_ERR_SUBTREE_MINMAX NID_crl_reason OP_NETSCAPE_CHALLENGE_BUG X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 NID_delta_crl OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_ALGORITHM NID_des_cbc OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_CURVE NID_des_cfb64 OP_NON_EXPORT_FIRST X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM NID_des_ecb OP_NO_ANTI_REPLAY X509_V_ERR_SUITE_B_INVALID_VERSION NID_des_ede OP_NO_CLIENT_RENEGOTIATION X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED NID_des_ede3 OP_NO_COMPRESSION X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY NID_des_ede3_cbc OP_NO_ENCRYPT_THEN_MAC X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE NID_des_ede3_cfb64 OP_NO_QUERY_MTU X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE NID_des_ede3_ofb64 OP_NO_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL NID_des_ede_cbc OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER NID_des_ede_cfb64 OP_NO_SSL_MASK X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT NID_des_ede_ofb64 OP_NO_SSLv2 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY NID_des_ofb64 OP_NO_SSLv3 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE NID_description OP_NO_TICKET X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION NID_desx_cbc OP_NO_TLSv1 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION NID_dhKeyAgreement OP_NO_TLSv1_1 X509_V_ERR_UNNESTED_RESOURCE NID_dnQualifier OP_NO_TLSv1_2 X509_V_ERR_UNSPECIFIED NID_dsa OP_NO_TLSv1_3 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX NID_dsaWithSHA OP_PKCS1_CHECK_1 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE NID_dsaWithSHA1 OP_PKCS1_CHECK_2 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE NID_dsaWithSHA1_2 OP_PRIORITIZE_CHACHA X509_V_ERR_UNSUPPORTED_NAME_SYNTAX NID_dsa_2 OP_SAFARI_ECDHE_ECDSA_BUG X509_V_FLAG_ALLOW_PROXY_CERTS NID_email_protect OP_SINGLE_DH_USE X509_V_FLAG_CB_ISSUER_CHECK NID_ext_key_usage OP_SINGLE_ECDH_USE X509_V_FLAG_CHECK_SS_SIGNATURE NID_ext_req OP_SSLEAY_080_CLIENT_DH_BUG X509_V_FLAG_CRL_CHECK NID_friendlyName OP_SSLREF2_REUSE_CERT_TYPE_BUG X509_V_FLAG_CRL_CHECK_ALL NID_givenName OP_TLSEXT_PADDING X509_V_FLAG_EXPLICIT_POLICY NID_hmacWithSHA1 OP_TLS_BLOCK_PADDING_BUG X509_V_FLAG_EXTENDED_CRL_SUPPORT NID_id_ad OP_TLS_D5_BUG X509_V_FLAG_IGNORE_CRITICAL NID_id_ce OP_TLS_ROLLBACK_BUG X509_V_FLAG_INHIBIT_ANY NID_id_kp READING X509_V_FLAG_INHIBIT_MAP NID_id_pbkdf2 RECEIVED_SHUTDOWN X509_V_FLAG_NOTIFY_POLICY NID_id_pe RSA_3 X509_V_FLAG_NO_ALT_CHAINS NID_id_pkix RSA_F4 X509_V_FLAG_NO_CHECK_TIME NID_id_qt_cps R_BAD_AUTHENTICATION_TYPE X509_V_FLAG_PARTIAL_CHAIN NID_id_qt_unotice R_BAD_CHECKSUM X509_V_FLAG_POLICY_CHECK NID_idea_cbc R_BAD_MAC_DECODE X509_V_FLAG_POLICY_MASK NID_idea_cfb64 R_BAD_RESPONSE_ARGUMENT X509_V_FLAG_SUITEB_128_LOS NID_idea_ecb R_BAD_SSL_FILETYPE X509_V_FLAG_SUITEB_128_LOS_ONLY NID_idea_ofb64 R_BAD_SSL_SESSION_ID_LENGTH X509_V_FLAG_SUITEB_192_LOS NID_info_access R_BAD_STATE X509_V_FLAG_TRUSTED_FIRST NID_initials R_BAD_WRITE_RETRY X509_V_FLAG_USE_CHECK_TIME NID_invalidity_date R_CHALLENGE_IS_DIFFERENT X509_V_FLAG_USE_DELTAS NID_issuer_alt_name R_CIPHER_TABLE_SRC_ERROR X509_V_FLAG_X509_STRICT NID_keyBag R_INVALID_CHALLENGE_LENGTH X509_V_OK NID_key_usage R_NO_CERTIFICATE_SET XN_FLAG_COMPAT NID_localKeyID R_NO_CERTIFICATE_SPECIFIED XN_FLAG_DN_REV NID_localityName R_NO_CIPHER_LIST XN_FLAG_DUMP_UNKNOWN_FIELDS NID_md2 R_NO_CIPHER_MATCH XN_FLAG_FN_ALIGN NID_md2WithRSAEncryption R_NO_PRIVATEKEY XN_FLAG_FN_LN NID_md5 R_NO_PUBLICKEY XN_FLAG_FN_MASK NID_md5WithRSA R_NULL_SSL_CTX XN_FLAG_FN_NONE NID_md5WithRSAEncryption R_PEER_DID_NOT_RETURN_A_CERTIFICATE XN_FLAG_FN_OID NID_md5_sha1 R_PEER_ERROR XN_FLAG_FN_SN NID_mdc2 R_PEER_ERROR_CERTIFICATE XN_FLAG_MULTILINE NID_mdc2WithRSA R_PEER_ERROR_NO_CIPHER XN_FLAG_ONELINE NID_ms_code_com R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE XN_FLAG_RFC2253 NID_ms_code_ind R_PUBLIC_KEY_ENCRYPT_ERROR XN_FLAG_SEP_COMMA_PLUS NID_ms_ctl_sign R_PUBLIC_KEY_IS_NOT_RSA XN_FLAG_SEP_CPLUS_SPC NID_ms_efs R_READ_WRONG_PACKET_TYPE XN_FLAG_SEP_MASK NID_ms_ext_req R_SHORT_READ XN_FLAG_SEP_MULTILINE NID_ms_sgc R_SSL_SESSION_ID_IS_DIFFERENT XN_FLAG_SEP_SPLUS_SPC NID_name R_UNABLE_TO_EXTRACT_PUBLIC_KEY XN_FLAG_SPC_EQ =head2 INTERNAL ONLY functions (do not use these) The following functions are not intended for use from outside of L module. They might be removed, renamed or changed without prior notice in future version. Simply B! =over =item * hello =item * blength =item * constant =back =head1 EXAMPLES One very good example to look at is the implementation of C in the C file. The following is a simple SSLeay client (with too little error checking :-( #!/usr/bin/perl use Socket; use Net::SSLeay qw(die_now die_if_ssl_error) ; Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); ($dest_serv, $port, $msg) = @ARGV; # Read command line $port = getservbyname ($port, 'tcp') unless $port =~ /^\d+$/; $dest_ip = gethostbyname ($dest_serv); $dest_serv_params = sockaddr_in($port, $dest_ip); socket (S, &AF_INET, &SOCK_STREAM, 0) or die "socket: $!"; connect (S, $dest_serv_params) or die "connect: $!"; select (S); $| = 1; select (STDOUT); # Eliminate STDIO buffering # The network connection is now open, lets fire up SSL $ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL) or die_if_ssl_error("ssl ctx set options"); $ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!"); Net::SSLeay::set_fd($ssl, fileno(S)); # Must use fileno $res = Net::SSLeay::connect($ssl) and die_if_ssl_error("ssl connect"); print "Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n"; # Exchange data $res = Net::SSLeay::write($ssl, $msg); # Perl knows how long $msg is die_if_ssl_error("ssl write"); CORE::shutdown S, 1; # Half close --> No more output, sends EOF to server $got = Net::SSLeay::read($ssl); # Perl returns undef on failure die_if_ssl_error("ssl read"); print $got; Net::SSLeay::free ($ssl); # Tear down connection Net::SSLeay::CTX_free ($ctx); close S; The following is a simple SSLeay echo server (non forking): #!/usr/bin/perl -w use Socket; use Net::SSLeay qw(die_now die_if_ssl_error); Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); $our_ip = "\0\0\0\0"; # Bind to all interfaces $port = 1235; $sockaddr_template = 'S n a4 x8'; $our_serv_params = pack ($sockaddr_template, &AF_INET, $port, $our_ip); socket (S, &AF_INET, &SOCK_STREAM, 0) or die "socket: $!"; bind (S, $our_serv_params) or die "bind: $!"; listen (S, 5) or die "listen: $!"; $ctx = Net::SSLeay::CTX_new () or die_now("CTX_new ($ctx): $!"); Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL) or die_if_ssl_error("ssl ctx set options"); # Following will ask password unless private key is not encrypted Net::SSLeay::CTX_use_RSAPrivateKey_file ($ctx, 'plain-rsa.pem', &Net::SSLeay::FILETYPE_PEM); die_if_ssl_error("private key"); Net::SSLeay::CTX_use_certificate_file ($ctx, 'plain-cert.pem', &Net::SSLeay::FILETYPE_PEM); die_if_ssl_error("certificate"); while (1) { print "Accepting connections...\n"; ($addr = accept (NS, S)) or die "accept: $!"; select (NS); $| = 1; select (STDOUT); # Piping hot! ($af,$client_port,$client_ip) = unpack($sockaddr_template,$addr); @inetaddr = unpack('C4',$client_ip); print "$af connection from " . join ('.', @inetaddr) . ":$client_port\n"; # We now have a network connection, lets fire up SSLeay... $ssl = Net::SSLeay::new($ctx) or die_now("SSL_new ($ssl): $!"); Net::SSLeay::set_fd($ssl, fileno(NS)); $err = Net::SSLeay::accept($ssl) and die_if_ssl_error('ssl accept'); print "Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n"; # Connected. Exchange some data. $got = Net::SSLeay::read($ssl); # Returns undef on fail die_if_ssl_error("ssl read"); print "Got `$got' (" . length ($got) . " chars)\n"; Net::SSLeay::write ($ssl, uc ($got)) or die "write: $!"; die_if_ssl_error("ssl write"); Net::SSLeay::free ($ssl); # Tear down connection close NS; } Yet another echo server. This one runs from C so it avoids all the socket code overhead. Only caveat is opening an rsa key file - it had better be without any encryption or else it will not know where to ask for the password. Note how C and C are wired to SSL. #!/usr/bin/perl # /etc/inetd.conf # ssltst stream tcp nowait root /path/to/server.pl server.pl # /etc/services # ssltst 1234/tcp use Net::SSLeay qw(die_now die_if_ssl_error); Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); chdir '/key/dir' or die "chdir: $!"; $| = 1; # Piping hot! open LOG, ">>/dev/console" or die "Can't open log file $!"; select LOG; print "server.pl started\n"; $ctx = Net::SSLeay::CTX_new() or die_now "CTX_new ($ctx) ($!)"; $ssl = Net::SSLeay::new($ctx) or die_now "new ($ssl) ($!)"; Net::SSLeay::set_options($ssl, &Net::SSLeay::OP_ALL) and die_if_ssl_error("ssl set options"); # We get already open network connection from inetd, now we just # need to attach SSLeay to STDIN and STDOUT Net::SSLeay::set_rfd($ssl, fileno(STDIN)); Net::SSLeay::set_wfd($ssl, fileno(STDOUT)); Net::SSLeay::use_RSAPrivateKey_file ($ssl, 'plain-rsa.pem', Net::SSLeay::FILETYPE_PEM); die_if_ssl_error("private key"); Net::SSLeay::use_certificate_file ($ssl, 'plain-cert.pem', Net::SSLeay::FILETYPE_PEM); die_if_ssl_error("certificate"); Net::SSLeay::accept($ssl) and die_if_ssl_err("ssl accept: $!"); print "Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n"; $got = Net::SSLeay::read($ssl); die_if_ssl_error("ssl read"); print "Got `$got' (" . length ($got) . " chars)\n"; Net::SSLeay::write ($ssl, uc($got)) or die "write: $!"; die_if_ssl_error("ssl write"); Net::SSLeay::free ($ssl); # Tear down the connection Net::SSLeay::CTX_free ($ctx); close LOG; There are also a number of example/test programs in the examples directory: sslecho.pl - A simple server, not unlike the one above minicli.pl - Implements a client using low level SSLeay routines sslcat.pl - Demonstrates using high level sslcat utility function get_page.pl - Is a utility for getting html pages from secure servers callback.pl - Demonstrates certificate verification and callback usage stdio_bulk.pl - Does SSL over Unix pipes ssl-inetd-serv.pl - SSL server that can be invoked from inetd.conf httpd-proxy-snif.pl - Utility that allows you to see how a browser sends https request to given server and what reply it gets back (very educative :-) makecert.pl - Creates a self signed cert (does not use this module) =head1 INSTALLATION See README and README.* in the distribution directory for installation guidance on a variety of platforms. =head1 LIMITATIONS C uses an internal buffer of 32KB, thus no single read will return more. In practice one read returns much less, usually as much as fits in one network packet. To work around this, you should use a loop like this: $reply = ''; while ($got = Net::SSLeay::read($ssl)) { last if print_errs('SSL_read'); $reply .= $got; } Although there is no built-in limit in C, the network packet size limitation applies here as well, thus use: $written = 0; while ($written < length($message)) { $written += Net::SSLeay::write($ssl, substr($message, $written)); last if print_errs('SSL_write'); } Or alternatively you can just use the following convenience functions: Net::SSLeay::ssl_write_all($ssl, $message) or die "ssl write failure"; $got = Net::SSLeay::ssl_read_all($ssl) or die "ssl read failure"; =head1 KNOWN BUGS AND CAVEATS An OpenSSL bug CVE-2015-0290 "OpenSSL Multiblock Corrupted Pointer Issue" can cause POST requests of over 90kB to fail or crash. This bug is reported to be fixed in OpenSSL 1.0.2a. Autoloader emits a Argument "xxx" isn't numeric in entersub at blib/lib/Net/SSLeay.pm' warning if die_if_ssl_error is made autoloadable. If you figure out why, drop me a line. Callback set using C does not appear to work. This may well be an openssl problem (e.g. see C line 1029). Try using C instead and do not be surprised if even this stops working in future versions. Callback and certificate verification stuff is generally too little tested. Random numbers are not initialized randomly enough, especially if you do not have C and/or C (such as in Solaris platforms - but it's been suggested that cryptorand daemon from the SUNski package solves this). In this case you should investigate third party software that can emulate these devices, e.g. by way of a named pipe to some program. Another gotcha with random number initialization is randomness depletion. This phenomenon, which has been extensively discussed in OpenSSL, Apache-SSL, and Apache-mod_ssl forums, can cause your script to block if you use C or to operate insecurely if you use C. What happens is that when too much randomness is drawn from the operating system's randomness pool then randomness can temporarily be unavailable. C solves this problem by waiting until enough randomness can be gathered - and this can take a long time since blocking reduces activity in the machine and less activity provides less random events: a vicious circle. C solves this dilemma more pragmatically by simply returning predictable "random" numbers. SomeC< /dev/urandom> emulation software however actually seems to implement C semantics. Caveat emptor. I've been pointed to two such daemons by Mik Firestone who has used them on Solaris 8: =over =item 1 Entropy Gathering Daemon (EGD) at L =item 2 Pseudo-random number generating daemon (PRNGD) at L =back If you are using the low level API functions to communicate with other SSL implementations, you would do well to call Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL) or die_if_ssl_error("ssl ctx set options"); to cope with some well know bugs in some other SSL implementations. The high level API functions always set all known compatibility options. Sometimes C (and the high level HTTPS functions that build on it) is too fast in signaling the EOF to legacy HTTPS servers. This causes the server to return empty page. To work around this problem you can set the global variable $Net::SSLeay::slowly = 1; # Add sleep so broken servers can keep up HTTP/1.1 is not supported. Specifically this module does not know to issue or serve multiple http requests per connection. This is a serious shortcoming, but using the SSL session cache on your server helps to alleviate the CPU load somewhat. As of version 1.09 many newer OpenSSL auxiliary functions were added (from C onwards in C). Unfortunately I have not had any opportunity to test these. Some of them are trivial enough that I believe they "just work", but others have rather complex interfaces with function pointers and all. In these cases you should proceed wit great caution. This module defaults to using OpenSSL automatic protocol negotiation code for automatically detecting the version of the SSL/TLS protocol that the other end talks. With most web servers this works just fine, but once in a while I get complaints from people that the module does not work with some web servers. Usually this can be solved by explicitly setting the protocol version, e.g. $Net::SSLeay::ssl_version = 2; # Insist on SSLv2 $Net::SSLeay::ssl_version = 3; # Insist on SSLv3 $Net::SSLeay::ssl_version = 10; # Insist on TLSv1 $Net::SSLeay::ssl_version = 11; # Insist on TLSv1.1 $Net::SSLeay::ssl_version = 12; # Insist on TLSv1.2 $Net::SSLeay::ssl_version = 13; # Insist on TLSv1.3 Although the autonegotiation is nice to have, the SSL standards do not formally specify any such mechanism. Most of the world has accepted the SSLeay/OpenSSL way of doing it as the de facto standard. But for the few that think differently, you have to explicitly speak the correct version. This is not really a bug, but rather a deficiency in the standards. If a site refuses to respond or sends back some nonsensical error codes (at the SSL handshake level), try this option before mailing me. On some systems, OpenSSL may be compiled without support for SSLv2. If this is the case, Net::SSLeay will warn if ssl_version has been set to 2. The high level API returns the certificate of the peer, thus allowing one to check what certificate was supplied. However, you will only be able to check the certificate after the fact, i.e. you already sent your form data by the time you find out that you did not trust them, oops. So, while being able to know the certificate after the fact is surely useful, the security minded would still choose to do the connection and certificate verification first and only then exchange data with the site. Currently none of the high level API functions do this, thus you would have to program it using the low level API. A good place to start is to see how the C function is implemented. The high level API functions use a global file handle C internally. This really should not be a problem because there is no way to interleave the high level API functions, unless you use threads (but threads are not very well supported in perl anyway). However, you may run into problems if you call undocumented internal functions in an interleaved fashion. The best solution is to "require Net::SSLeay" in one thread after all the threads have been created. =head1 DIAGNOSTICS =over =item Random number generator not seeded!!! B<(W)> This warning indicates that C was not able to read C or C, possibly because your system does not have them or they are differently named. You can still use SSL, but the encryption will not be as strong. =item open_tcp_connection: destination host not found:`server' (port 123) ($!) Name lookup for host named C failed. =item open_tcp_connection: failed `server', 123 ($!) The name was resolved, but establishing the TCP connection failed. =item msg 123: 1 - error:140770F8:SSL routines:SSL23_GET_SERVER_HELLO:unknown proto SSLeay error string. The first number (123) is the PID, the second number (1) indicates the position of the error message in SSLeay error stack. You often see a pile of these messages as errors cascade. =item msg 123: 1 - error:02001002::lib(2) :func(1) :reason(2) The same as above, but you didn't call load_error_strings() so SSLeay couldn't verbosely explain the error. You can still find out what it means with this command: /usr/local/ssl/bin/ssleay errstr 02001002 =item Password is being asked for private key This is normal behaviour if your private key is encrypted. Either you have to supply the password or you have to use an unencrypted private key. Scan OpenSSL.org for the FAQ that explains how to do this (or just study examples/makecert.pl which is used during C to do just that). =back =head1 SECURITY You can mitigate some of the security vulnerabilities that might be present in your SSL/TLS application: =head2 BEAST Attack http://blogs.cisco.com/security/beat-the-beast-with-tls/ https://community.qualys.com/blogs/securitylabs/2011/10/17/mitigating-the-beast-attack-on-tls http://blog.zoller.lu/2011/09/beast-summary-tls-cbc-countermeasures.html The BEAST attack relies on a weakness in the way CBC mode is used in SSL/TLS. In OpenSSL versions 0.9.6d and later, the protocol-level mitigation is enabled by default, thus making it not vulnerable to the BEAST attack. Solutions: =over =item * Compile with OpenSSL versions 0.9.6d or later, which enables SSL_OP_ALL by default =item * Ensure SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS is not enabled (its not enabled by default) =item * Don't support SSLv2, SSLv3 =item * Actively control the ciphers your server supports with set_cipher_list: =back Net::SSLeay::set_cipher_list($ssl, 'RC4-SHA:HIGH:!ADH'); =head2 Session Resumption http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html The SSL Labs vulnerability test on your SSL server might report in red: Session resumption No (IDs assigned but not accepted) This report is not really bug or a vulnerability, since the server will not accept session resumption requests. However, you can prevent this noise in the report by disabling the session cache altogether: Net::SSLeay::CTX_set_session_cache_mode($ssl_ctx, Net::SSLeay::SESS_CACHE_OFF()); Use 0 if you don't have SESS_CACHE_OFF constant. =head2 Secure Renegotiation and DoS Attack https://community.qualys.com/blogs/securitylabs/2011/10/31/tls-renegotiation-and-denial-of-service-attacks This is not a "security flaw," it is more of a DoS vulnerability. Solutions: =over =item * Do not support SSLv2 =item * Do not set the SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION option =item * Compile with OpenSSL 0.9.8m or later =back =head1 BUGS If you encounter a problem with this module that you believe is a bug, please report it in one of the following ways: =over =item * L under the Net-SSLeay GitHub project at L; =item * L using the CPAN RT bug tracker's web interface at L; =item * send an email to the CPAN RT bug tracker at L. =back Please make sure your bug report includes the following information: =over =item * the code you are trying to run; =item * your operating system name and version; =item * the output of C; =item * the version of OpenSSL or LibreSSL you are using. =back =head1 AUTHOR Originally written by Sampo Kellomäki. Maintained by Florian Ragwitz between November 2005 and January 2010. Maintained by Mike McCauley between November 2005 and June 2018. Maintained by Chris Novakovic, Tuure Vartiainen and Heikki Vatiainen since June 2018. =head1 COPYRIGHT Copyright (c) 1996-2003 Sampo Kellomäki Copyright (c) 2005-2010 Florian Ragwitz Copyright (c) 2005-2018 Mike McCauley Copyright (c) 2018- Chris Novakovic Copyright (c) 2018- Tuure Vartiainen Copyright (c) 2018- Heikki Vatiainen All rights reserved. =head1 LICENSE This module is released under the terms of the Artistic License 2.0. For details, see the C file distributed with Net-SSLeay's source code. =head1 SEE ALSO Net::SSLeay::Handle - File handle interface ./examples - Example servers and a clients - OpenSSL source, documentation, etc openssl-users-request@openssl.org - General OpenSSL mailing list - TLS 1.0 specification - HTTP specifications - How to send password - Entropy Gathering Daemon (EGD) - pseudo-random number generating daemon (PRNGD) perl(1) perlref(1) perllol(1) perldoc ~openssl/doc/ssl/SSL_CTX_set_verify.pod PKR1]V~**SSLeay/Handle.pmnu[package Net::SSLeay::Handle; use 5.8.1; use strict; use Socket; use Net::SSLeay; require Exporter; =encoding utf-8 =head1 NAME Net::SSLeay::Handle - Perl module that lets SSL (HTTPS) sockets be handled as standard file handles. =head1 SYNOPSIS use Net::SSLeay::Handle qw/shutdown/; my ($host, $port) = ("localhost", 443); tie(*SSL, "Net::SSLeay::Handle", $host, $port); print SSL "GET / HTTP/1.0\r\n"; shutdown(\*SSL, 1); print while (); close SSL; =head1 DESCRIPTION Net::SSLeay::Handle allows you to request and receive HTTPS web pages using "old-fashion" file handles as in: print SSL "GET / HTTP/1.0\r\n"; and print while (); If you export the shutdown routine, then the only extra code that you need to add to your program is the tie function as in: my $socket; if ($scheme eq "https") { tie(*S2, "Net::SSLeay::Handle", $host, $port); $socket = \*S2; else { $socket = Net::SSLeay::Handle->make_socket($host, $port); } print $socket $request_headers; ... =cut use vars qw(@ISA @EXPORT_OK $VERSION); @ISA = qw(Exporter); @EXPORT_OK = qw(shutdown); $VERSION = '1.88'; my $Initialized; #-- only _initialize() once my $Debug = 0; #-- pretty hokey #== Tie Handle Methods ======================================================== # # see perldoc perltie for details. # #============================================================================== sub TIEHANDLE { my ($class, $socket, $port) = @_; $Debug > 10 and print "TIEHANDLE(@{[join ', ', @_]})\n"; ref $socket eq "GLOB" or $socket = $class->make_socket($socket, $port); $class->_initialize(); my $ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); my $ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!"); my $fileno = fileno($socket); Net::SSLeay::set_fd($ssl, $fileno); # Must use fileno my $resp = Net::SSLeay::connect($ssl); $Debug and print "Cipher '" . Net::SSLeay::get_cipher($ssl) . "'\n"; my $self = bless { ssl => $ssl, ctx => $ctx, socket => $socket, fileno => $fileno, }, $class; return $self; } sub PRINT { my $self = shift; my $ssl = _get_ssl($self); my $resp = 0; for my $msg (@_) { defined $msg or last; $resp = Net::SSLeay::write($ssl, $msg) or last; } return $resp; } sub READLINE { my $self = shift; my $ssl = _get_ssl($self); if (wantarray) { my @lines; while (my $line = Net::SSLeay::ssl_read_until($ssl)) { push @lines, $line; } return @lines; } else { my $line = Net::SSLeay::ssl_read_until($ssl); return $line ? $line : undef; } } sub READ { my ($self, $buf, $len, $offset) = \ (@_); my $ssl = _get_ssl($$self); defined($$offset) or return length($$buf = Net::SSLeay::ssl_read_all($ssl, $$len)); defined(my $read = Net::SSLeay::ssl_read_all($ssl, $$len)) or return undef; my $buf_len = length($$buf); $$offset > $buf_len and $$buf .= chr(0) x ($$offset - $buf_len); substr($$buf, $$offset) = $read; return length($read); } sub WRITE { my $self = shift; my ($buf, $len, $offset) = @_; $offset = 0 unless defined $offset; # Return number of characters written. my $ssl = $self->_get_ssl(); return $len if Net::SSLeay::write($ssl, substr($buf, $offset, $len)); return undef; } sub CLOSE { my $self = shift; my $fileno = $self->{fileno}; $Debug > 10 and print "close($fileno)\n"; Net::SSLeay::free ($self->{ssl}); Net::SSLeay::CTX_free ($self->{ctx}); close $self->{socket}; } sub FILENO { $_[0]->{fileno} } =head1 FUNCTIONS =over =item shutdown shutdown(\*SOCKET, $mode) Calls to the main shutdown() don't work with tied sockets created with this module. This shutdown should be able to distinquish between tied and untied sockets and do the right thing. =cut sub shutdown { my ($obj, @params) = @_; my $socket = UNIVERSAL::isa($obj, 'Net::SSLeay::Handle') ? $obj->{socket} : $obj; return shutdown($socket, @params); } =item debug my $debug = Net::SSLeay::Handle->debug() Net::SSLeay::Handle->debug(1) Get/set debugging mode. Always returns the debug value before the function call. if an additional argument is given the debug option will be set to this value. =cut sub debug { my ($class, $debug) = @_; my $old_debug = $Debug; @_ >1 and $Debug = $debug || 0; return $old_debug; } #=== Internal Methods ========================================================= =item make_socket my $sock = Net::SSLeay::Handle->make_socket($host, $port); Creates a socket that is connected to $post using $port. It uses $Net::SSLeay::proxyhost and proxyport if set and authentificates itself against this proxy depending on $Net::SSLeay::proxyauth. It also turns autoflush on for the created socket. =cut sub make_socket { my ($class, $host, $port) = @_; $Debug > 10 and print "_make_socket(@{[join ', ', @_]})\n"; $host ||= 'localhost'; $port ||= 443; my $phost = $Net::SSLeay::proxyhost; my $pport = $Net::SSLeay::proxyhost ? $Net::SSLeay::proxyport : $port; my $dest_ip = gethostbyname($phost || $host); my $host_params = sockaddr_in($pport, $dest_ip); socket(my $socket, &PF_INET(), &SOCK_STREAM(), 0) or die "socket: $!"; connect($socket, $host_params) or die "connect: $!"; my $old_select = select($socket); $| = 1; select($old_select); $phost and do { my $auth = $Net::SSLeay::proxyauth; my $CRLF = $Net::SSLeay::CRLF; print $socket "CONNECT $host:$port HTTP/1.0$auth$CRLF$CRLF"; my $line = <$socket>; }; return $socket; } =back =cut sub _initialize { $Initialized++ and return; Net::SSLeay::load_error_strings(); Net::SSLeay::SSLeay_add_ssl_algorithms(); Net::SSLeay::randomize(); } sub __dummy { my $host = $Net::SSLeay::proxyhost; my $port = $Net::SSLeay::proxyport; my $auth = $Net::SSLeay::proxyauth; } #--- _get_self($socket) ------------------------------------------------------- # Returns a hash containing attributes for $socket (= \*SOMETHING) based # on fileno($socket). Will return undef if $socket was not created here. #------------------------------------------------------------------------------ sub _get_self { return $_[0]; } #--- _get_ssl($socket) -------------------------------------------------------- # Returns a the "ssl" attribute for $socket (= \*SOMETHING) based # on fileno($socket). Will cause a warning and return undef if $socket was not # created here. #------------------------------------------------------------------------------ sub _get_ssl { return $_[0]->{ssl}; } 1; __END__ =head2 USING EXISTING SOCKETS One of the motivations for writing this module was to avoid duplicating socket creation code (which is mostly error handling). The calls to tie() above where it is passed a $host and $port is provided for convenience testing. If you already have a socket connected to the right host and port, S1, then you can do something like: my $socket \*S1; if ($scheme eq "https") { tie(*S2, "Net::SSLeay::Handle", $socket); $socket = \*S2; } my $last_sel = select($socket); $| = 1; select($last_sel); print $socket $request_headers; ... Note: As far as I know you must be careful with the globs in the tie() function. The first parameter must be a glob (*SOMETHING) and the last parameter must be a reference to a glob (\*SOMETHING_ELSE) or a scaler that was assigned to a reference to a glob (as in the example above) Also, the two globs must be different. When I tried to use the same glob, I got a core dump. =head2 EXPORT None by default. You can export the shutdown() function. It is suggested that you do export shutdown() or use the fully qualified Net::SSLeay::Handle::shutdown() function to shutdown SSL sockets. It should be smart enough to distinguish between SSL and non-SSL sockets and do the right thing. =head1 EXAMPLES use Net::SSLeay::Handle qw/shutdown/; my ($host, $port) = ("localhost", 443); tie(*SSL, "Net::SSLeay::Handle", $host, $port); print SSL "GET / HTTP/1.0\r\n"; shutdown(\*SSL, 1); print while (); close SSL; =head1 TODO Better error handling. Callback routine? =head1 CAVEATS Tying to a file handle is a little tricky (for me at least). The first parameter to tie() must be a glob (*SOMETHING) and the last parameter must be a reference to a glob (\*SOMETHING_ELSE) or a scaler that was assigned to a reference to a glob ($s = \*SOMETHING_ELSE). Also, the two globs must be different. When I tried to use the same glob, I got a core dump. I was able to associate attributes to globs created by this module (like *SSL above) by making a hash of hashes keyed by the file head1. =head1 CHANGES Please see Net-SSLeay-Handle-0.50/Changes file. =head1 BUGS If you encounter a problem with this module that you believe is a bug, please report it in one of the following ways: =over =item * L under the Net-SSLeay GitHub project at L; =item * L using the CPAN RT bug tracker's web interface at L; =item * send an email to the CPAN RT bug tracker at L. =back Please make sure your bug report includes the following information: =over =item * the code you are trying to run; =item * your operating system name and version; =item * the output of C; =item * the version of OpenSSL or LibreSSL you are using. =back =head1 AUTHOR Originally written by Jim Bowlin. Maintained by Sampo Kellomäki between July 2001 and August 2003. Maintained by Florian Ragwitz between November 2005 and January 2010. Maintained by Mike McCauley between November 2005 and June 2018. Maintained by Chris Novakovic, Tuure Vartiainen and Heikki Vatiainen since June 2018. =head1 COPYRIGHT Copyright (c) 2001 Jim Bowlin Copyright (c) 2001-2003 Sampo Kellomäki Copyright (c) 2005-2010 Florian Ragwitz Copyright (c) 2005-2018 Mike McCauley Copyright (c) 2018- Chris Novakovic Copyright (c) 2018- Tuure Vartiainen Copyright (c) 2018- Heikki Vatiainen All rights reserved. =head1 LICENSE This module is released under the terms of the Artistic License 2.0. For details, see the C file distributed with Net-SSLeay's source code. =head1 SEE ALSO Net::SSLeay, perl(1), http://openssl.org/ =cut PKR1]^ SSLeay.pmnu[# Net::SSLeay.pm - Perl module for using Eric Young's implementation of SSL # # Copyright (c) 1996-2003 Sampo Kellomäki # Copyright (c) 2005-2010 Florian Ragwitz # Copyright (c) 2005-2018 Mike McCauley # Copyright (c) 2018- Chris Novakovic # Copyright (c) 2018- Tuure Vartiainen # Copyright (c) 2018- Heikki Vatiainen # # All rights reserved. # # This module is released under the terms of the Artistic License 2.0. For # details, see the LICENSE file distributed with Net-SSLeay's source code. package Net::SSLeay; use 5.8.1; use strict; use Carp; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD $CRLF); use Socket; use Errno; require Exporter; use AutoLoader; # 0=no warns, 1=only errors, 2=ciphers, 3=progress, 4=dump data $Net::SSLeay::trace = 0; # Do not change here, use # $Net::SSLeay::trace = [1-4] in caller # 2 = insist on v2 SSL protocol # 3 = insist on v3 SSL # 10 = insist on TLSv1 # 11 = insist on TLSv1.1 # 12 = insist on TLSv1.2 # 13 = insist on TLSv1.3 # 0 or undef = guess (v23) # $Net::SSLeay::ssl_version = 0; # don't change here, use # Net::SSLeay::version=[2,3,0] in caller #define to enable the "cat /proc/$$/stat" stuff $Net::SSLeay::linux_debug = 0; # Number of seconds to sleep after sending message and before half # closing connection. Useful with antiquated broken servers. $Net::SSLeay::slowly = 0; # RANDOM NUMBER INITIALIZATION # # Edit to your taste. Using /dev/random would be more secure, but may # block if randomness is not available, thus the default is # /dev/urandom. $how_random determines how many bits of randomness to take # from the device. You should take enough (read SSLeay/doc/rand), but # beware that randomness is limited resource so you should not waste # it either or you may end up with randomness depletion (situation where # /dev/random would block and /dev/urandom starts to return predictable # numbers). # # N.B. /dev/urandom does not exist on all systems, such as Solaris 2.6. In that # case you should get a third party package that emulates /dev/urandom # (e.g. via named pipe) or supply a random number file. Some such # packages are documented in Caveat section of the POD documentation. $Net::SSLeay::random_device = '/dev/urandom'; $Net::SSLeay::how_random = 512; $VERSION = '1.88'; # Also update $Net::SSLeay::Handle::VERSION @ISA = qw(Exporter); #BEWARE: # 3-columns part of @EXPORT_OK related to constants is the output of command: # perl helper_script/regen_openssl_constants.pl -gen-pod # if you add/remove any constant you need to update it manually @EXPORT_OK = qw( ASN1_STRFLGS_ESC_CTRL NID_netscape R_UNKNOWN_REMOTE_ERROR_TYPE ASN1_STRFLGS_ESC_MSB NID_netscape_base_url R_UNKNOWN_STATE ASN1_STRFLGS_ESC_QUOTE NID_netscape_ca_policy_url R_X509_LIB ASN1_STRFLGS_RFC2253 NID_netscape_ca_revocation_url SENT_SHUTDOWN CB_ACCEPT_EXIT NID_netscape_cert_extension SESSION_ASN1_VERSION CB_ACCEPT_LOOP NID_netscape_cert_sequence SESS_CACHE_BOTH CB_ALERT NID_netscape_cert_type SESS_CACHE_CLIENT CB_CONNECT_EXIT NID_netscape_comment SESS_CACHE_NO_AUTO_CLEAR CB_CONNECT_LOOP NID_netscape_data_type SESS_CACHE_NO_INTERNAL CB_EXIT NID_netscape_renewal_url SESS_CACHE_NO_INTERNAL_LOOKUP CB_HANDSHAKE_DONE NID_netscape_revocation_url SESS_CACHE_NO_INTERNAL_STORE CB_HANDSHAKE_START NID_netscape_ssl_server_name SESS_CACHE_OFF CB_LOOP NID_ns_sgc SESS_CACHE_SERVER CB_READ NID_organizationName SSL3_VERSION CB_READ_ALERT NID_organizationalUnitName SSLEAY_BUILT_ON CB_WRITE NID_pbeWithMD2AndDES_CBC SSLEAY_CFLAGS CB_WRITE_ALERT NID_pbeWithMD2AndRC2_CBC SSLEAY_DIR ERROR_NONE NID_pbeWithMD5AndCast5_CBC SSLEAY_PLATFORM ERROR_SSL NID_pbeWithMD5AndDES_CBC SSLEAY_VERSION ERROR_SYSCALL NID_pbeWithMD5AndRC2_CBC ST_ACCEPT ERROR_WANT_ACCEPT NID_pbeWithSHA1AndDES_CBC ST_BEFORE ERROR_WANT_CONNECT NID_pbeWithSHA1AndRC2_CBC ST_CONNECT ERROR_WANT_READ NID_pbe_WithSHA1And128BitRC2_CBC ST_INIT ERROR_WANT_WRITE NID_pbe_WithSHA1And128BitRC4 ST_OK ERROR_WANT_X509_LOOKUP NID_pbe_WithSHA1And2_Key_TripleDES_CBC ST_READ_BODY ERROR_ZERO_RETURN NID_pbe_WithSHA1And3_Key_TripleDES_CBC ST_READ_HEADER EVP_PKS_DSA NID_pbe_WithSHA1And40BitRC2_CBC TLS1_1_VERSION EVP_PKS_EC NID_pbe_WithSHA1And40BitRC4 TLS1_2_VERSION EVP_PKS_RSA NID_pbes2 TLS1_3_VERSION EVP_PKT_ENC NID_pbmac1 TLS1_VERSION EVP_PKT_EXCH NID_pkcs TLSEXT_STATUSTYPE_ocsp EVP_PKT_EXP NID_pkcs3 VERIFY_CLIENT_ONCE EVP_PKT_SIGN NID_pkcs7 VERIFY_FAIL_IF_NO_PEER_CERT EVP_PK_DH NID_pkcs7_data VERIFY_NONE EVP_PK_DSA NID_pkcs7_digest VERIFY_PEER EVP_PK_EC NID_pkcs7_encrypted VERIFY_POST_HANDSHAKE EVP_PK_RSA NID_pkcs7_enveloped V_OCSP_CERTSTATUS_GOOD FILETYPE_ASN1 NID_pkcs7_signed V_OCSP_CERTSTATUS_REVOKED FILETYPE_PEM NID_pkcs7_signedAndEnveloped V_OCSP_CERTSTATUS_UNKNOWN F_CLIENT_CERTIFICATE NID_pkcs8ShroudedKeyBag WRITING F_CLIENT_HELLO NID_pkcs9 X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT F_CLIENT_MASTER_KEY NID_pkcs9_challengePassword X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS F_D2I_SSL_SESSION NID_pkcs9_contentType X509_CHECK_FLAG_NEVER_CHECK_SUBJECT F_GET_CLIENT_FINISHED NID_pkcs9_countersignature X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS F_GET_CLIENT_HELLO NID_pkcs9_emailAddress X509_CHECK_FLAG_NO_WILDCARDS F_GET_CLIENT_MASTER_KEY NID_pkcs9_extCertAttributes X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS F_GET_SERVER_FINISHED NID_pkcs9_messageDigest X509_FILETYPE_ASN1 F_GET_SERVER_HELLO NID_pkcs9_signingTime X509_FILETYPE_DEFAULT F_GET_SERVER_VERIFY NID_pkcs9_unstructuredAddress X509_FILETYPE_PEM F_I2D_SSL_SESSION NID_pkcs9_unstructuredName X509_LOOKUP F_READ_N NID_private_key_usage_period X509_PURPOSE_ANY F_REQUEST_CERTIFICATE NID_rc2_40_cbc X509_PURPOSE_CRL_SIGN F_SERVER_HELLO NID_rc2_64_cbc X509_PURPOSE_NS_SSL_SERVER F_SSL_CERT_NEW NID_rc2_cbc X509_PURPOSE_OCSP_HELPER F_SSL_GET_NEW_SESSION NID_rc2_cfb64 X509_PURPOSE_SMIME_ENCRYPT F_SSL_NEW NID_rc2_ecb X509_PURPOSE_SMIME_SIGN F_SSL_READ NID_rc2_ofb64 X509_PURPOSE_SSL_CLIENT F_SSL_RSA_PRIVATE_DECRYPT NID_rc4 X509_PURPOSE_SSL_SERVER F_SSL_RSA_PUBLIC_ENCRYPT NID_rc4_40 X509_PURPOSE_TIMESTAMP_SIGN F_SSL_SESSION_NEW NID_rc5_cbc X509_TRUST_COMPAT F_SSL_SESSION_PRINT_FP NID_rc5_cfb64 X509_TRUST_EMAIL F_SSL_SET_FD NID_rc5_ecb X509_TRUST_OBJECT_SIGN F_SSL_SET_RFD NID_rc5_ofb64 X509_TRUST_OCSP_REQUEST F_SSL_SET_WFD NID_ripemd160 X509_TRUST_OCSP_SIGN F_SSL_USE_CERTIFICATE NID_ripemd160WithRSA X509_TRUST_SSL_CLIENT F_SSL_USE_CERTIFICATE_ASN1 NID_rle_compression X509_TRUST_SSL_SERVER F_SSL_USE_CERTIFICATE_FILE NID_rsa X509_TRUST_TSA F_SSL_USE_PRIVATEKEY NID_rsaEncryption X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH F_SSL_USE_PRIVATEKEY_ASN1 NID_rsadsi X509_V_ERR_AKID_SKID_MISMATCH F_SSL_USE_PRIVATEKEY_FILE NID_safeContentsBag X509_V_ERR_APPLICATION_VERIFICATION F_SSL_USE_RSAPRIVATEKEY NID_sdsiCertificate X509_V_ERR_CA_KEY_TOO_SMALL F_SSL_USE_RSAPRIVATEKEY_ASN1 NID_secretBag X509_V_ERR_CA_MD_TOO_WEAK F_SSL_USE_RSAPRIVATEKEY_FILE NID_serialNumber X509_V_ERR_CERT_CHAIN_TOO_LONG F_WRITE_PENDING NID_server_auth X509_V_ERR_CERT_HAS_EXPIRED GEN_DIRNAME NID_sha X509_V_ERR_CERT_NOT_YET_VALID GEN_DNS NID_sha1 X509_V_ERR_CERT_REJECTED GEN_EDIPARTY NID_sha1WithRSA X509_V_ERR_CERT_REVOKED GEN_EMAIL NID_sha1WithRSAEncryption X509_V_ERR_CERT_SIGNATURE_FAILURE GEN_IPADD NID_shaWithRSAEncryption X509_V_ERR_CERT_UNTRUSTED GEN_OTHERNAME NID_stateOrProvinceName X509_V_ERR_CRL_HAS_EXPIRED GEN_RID NID_subject_alt_name X509_V_ERR_CRL_NOT_YET_VALID GEN_URI NID_subject_key_identifier X509_V_ERR_CRL_PATH_VALIDATION_ERROR GEN_X400 NID_surname X509_V_ERR_CRL_SIGNATURE_FAILURE LIBRESSL_VERSION_NUMBER NID_sxnet X509_V_ERR_DANE_NO_MATCH MBSTRING_ASC NID_time_stamp X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT MBSTRING_BMP NID_title X509_V_ERR_DIFFERENT_CRL_SCOPE MBSTRING_FLAG NID_undef X509_V_ERR_EE_KEY_TOO_SMALL MBSTRING_UNIV NID_uniqueIdentifier X509_V_ERR_EMAIL_MISMATCH MBSTRING_UTF8 NID_x509Certificate X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD MIN_RSA_MODULUS_LENGTH_IN_BYTES NID_x509Crl X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD MODE_ACCEPT_MOVING_WRITE_BUFFER NID_zlib_compression X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD MODE_AUTO_RETRY NOTHING X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD MODE_ENABLE_PARTIAL_WRITE OCSP_RESPONSE_STATUS_INTERNALERROR X509_V_ERR_EXCLUDED_VIOLATION MODE_RELEASE_BUFFERS OCSP_RESPONSE_STATUS_MALFORMEDREQUEST X509_V_ERR_HOSTNAME_MISMATCH NID_OCSP_sign OCSP_RESPONSE_STATUS_SIGREQUIRED X509_V_ERR_INVALID_CA NID_SMIMECapabilities OCSP_RESPONSE_STATUS_SUCCESSFUL X509_V_ERR_INVALID_CALL NID_X500 OCSP_RESPONSE_STATUS_TRYLATER X509_V_ERR_INVALID_EXTENSION NID_X509 OCSP_RESPONSE_STATUS_UNAUTHORIZED X509_V_ERR_INVALID_NON_CA NID_ad_OCSP OPENSSL_BUILT_ON X509_V_ERR_INVALID_POLICY_EXTENSION NID_ad_ca_issuers OPENSSL_CFLAGS X509_V_ERR_INVALID_PURPOSE NID_algorithm OPENSSL_DIR X509_V_ERR_IP_ADDRESS_MISMATCH NID_authority_key_identifier OPENSSL_ENGINES_DIR X509_V_ERR_KEYUSAGE_NO_CERTSIGN NID_basic_constraints OPENSSL_PLATFORM X509_V_ERR_KEYUSAGE_NO_CRL_SIGN NID_bf_cbc OPENSSL_VERSION X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE NID_bf_cfb64 OPENSSL_VERSION_NUMBER X509_V_ERR_NO_EXPLICIT_POLICY NID_bf_ecb OP_ALL X509_V_ERR_NO_VALID_SCTS NID_bf_ofb64 OP_ALLOW_NO_DHE_KEX X509_V_ERR_OCSP_CERT_UNKNOWN NID_cast5_cbc OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION X509_V_ERR_OCSP_VERIFY_FAILED NID_cast5_cfb64 OP_CIPHER_SERVER_PREFERENCE X509_V_ERR_OCSP_VERIFY_NEEDED NID_cast5_ecb OP_CISCO_ANYCONNECT X509_V_ERR_OUT_OF_MEM NID_cast5_ofb64 OP_COOKIE_EXCHANGE X509_V_ERR_PATH_LENGTH_EXCEEDED NID_certBag OP_CRYPTOPRO_TLSEXT_BUG X509_V_ERR_PATH_LOOP NID_certificate_policies OP_DONT_INSERT_EMPTY_FRAGMENTS X509_V_ERR_PERMITTED_VIOLATION NID_client_auth OP_ENABLE_MIDDLEBOX_COMPAT X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED NID_code_sign OP_EPHEMERAL_RSA X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED NID_commonName OP_LEGACY_SERVER_CONNECT X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION NID_countryName OP_MICROSOFT_BIG_SSLV3_BUFFER X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN NID_crlBag OP_MICROSOFT_SESS_ID_BUG X509_V_ERR_STORE_LOOKUP NID_crl_distribution_points OP_MSIE_SSLV2_RSA_PADDING X509_V_ERR_SUBJECT_ISSUER_MISMATCH NID_crl_number OP_NETSCAPE_CA_DN_BUG X509_V_ERR_SUBTREE_MINMAX NID_crl_reason OP_NETSCAPE_CHALLENGE_BUG X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 NID_delta_crl OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_ALGORITHM NID_des_cbc OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_CURVE NID_des_cfb64 OP_NON_EXPORT_FIRST X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM NID_des_ecb OP_NO_ANTI_REPLAY X509_V_ERR_SUITE_B_INVALID_VERSION NID_des_ede OP_NO_CLIENT_RENEGOTIATION X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED NID_des_ede3 OP_NO_COMPRESSION X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY NID_des_ede3_cbc OP_NO_ENCRYPT_THEN_MAC X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE NID_des_ede3_cfb64 OP_NO_QUERY_MTU X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE NID_des_ede3_ofb64 OP_NO_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL NID_des_ede_cbc OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER NID_des_ede_cfb64 OP_NO_SSL_MASK X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT NID_des_ede_ofb64 OP_NO_SSLv2 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY NID_des_ofb64 OP_NO_SSLv3 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE NID_description OP_NO_TICKET X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION NID_desx_cbc OP_NO_TLSv1 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION NID_dhKeyAgreement OP_NO_TLSv1_1 X509_V_ERR_UNNESTED_RESOURCE NID_dnQualifier OP_NO_TLSv1_2 X509_V_ERR_UNSPECIFIED NID_dsa OP_NO_TLSv1_3 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX NID_dsaWithSHA OP_PKCS1_CHECK_1 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE NID_dsaWithSHA1 OP_PKCS1_CHECK_2 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE NID_dsaWithSHA1_2 OP_PRIORITIZE_CHACHA X509_V_ERR_UNSUPPORTED_NAME_SYNTAX NID_dsa_2 OP_SAFARI_ECDHE_ECDSA_BUG X509_V_FLAG_ALLOW_PROXY_CERTS NID_email_protect OP_SINGLE_DH_USE X509_V_FLAG_CB_ISSUER_CHECK NID_ext_key_usage OP_SINGLE_ECDH_USE X509_V_FLAG_CHECK_SS_SIGNATURE NID_ext_req OP_SSLEAY_080_CLIENT_DH_BUG X509_V_FLAG_CRL_CHECK NID_friendlyName OP_SSLREF2_REUSE_CERT_TYPE_BUG X509_V_FLAG_CRL_CHECK_ALL NID_givenName OP_TLSEXT_PADDING X509_V_FLAG_EXPLICIT_POLICY NID_hmacWithSHA1 OP_TLS_BLOCK_PADDING_BUG X509_V_FLAG_EXTENDED_CRL_SUPPORT NID_id_ad OP_TLS_D5_BUG X509_V_FLAG_IGNORE_CRITICAL NID_id_ce OP_TLS_ROLLBACK_BUG X509_V_FLAG_INHIBIT_ANY NID_id_kp READING X509_V_FLAG_INHIBIT_MAP NID_id_pbkdf2 RECEIVED_SHUTDOWN X509_V_FLAG_NOTIFY_POLICY NID_id_pe RSA_3 X509_V_FLAG_NO_ALT_CHAINS NID_id_pkix RSA_F4 X509_V_FLAG_NO_CHECK_TIME NID_id_qt_cps R_BAD_AUTHENTICATION_TYPE X509_V_FLAG_PARTIAL_CHAIN NID_id_qt_unotice R_BAD_CHECKSUM X509_V_FLAG_POLICY_CHECK NID_idea_cbc R_BAD_MAC_DECODE X509_V_FLAG_POLICY_MASK NID_idea_cfb64 R_BAD_RESPONSE_ARGUMENT X509_V_FLAG_SUITEB_128_LOS NID_idea_ecb R_BAD_SSL_FILETYPE X509_V_FLAG_SUITEB_128_LOS_ONLY NID_idea_ofb64 R_BAD_SSL_SESSION_ID_LENGTH X509_V_FLAG_SUITEB_192_LOS NID_info_access R_BAD_STATE X509_V_FLAG_TRUSTED_FIRST NID_initials R_BAD_WRITE_RETRY X509_V_FLAG_USE_CHECK_TIME NID_invalidity_date R_CHALLENGE_IS_DIFFERENT X509_V_FLAG_USE_DELTAS NID_issuer_alt_name R_CIPHER_TABLE_SRC_ERROR X509_V_FLAG_X509_STRICT NID_keyBag R_INVALID_CHALLENGE_LENGTH X509_V_OK NID_key_usage R_NO_CERTIFICATE_SET XN_FLAG_COMPAT NID_localKeyID R_NO_CERTIFICATE_SPECIFIED XN_FLAG_DN_REV NID_localityName R_NO_CIPHER_LIST XN_FLAG_DUMP_UNKNOWN_FIELDS NID_md2 R_NO_CIPHER_MATCH XN_FLAG_FN_ALIGN NID_md2WithRSAEncryption R_NO_PRIVATEKEY XN_FLAG_FN_LN NID_md5 R_NO_PUBLICKEY XN_FLAG_FN_MASK NID_md5WithRSA R_NULL_SSL_CTX XN_FLAG_FN_NONE NID_md5WithRSAEncryption R_PEER_DID_NOT_RETURN_A_CERTIFICATE XN_FLAG_FN_OID NID_md5_sha1 R_PEER_ERROR XN_FLAG_FN_SN NID_mdc2 R_PEER_ERROR_CERTIFICATE XN_FLAG_MULTILINE NID_mdc2WithRSA R_PEER_ERROR_NO_CIPHER XN_FLAG_ONELINE NID_ms_code_com R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE XN_FLAG_RFC2253 NID_ms_code_ind R_PUBLIC_KEY_ENCRYPT_ERROR XN_FLAG_SEP_COMMA_PLUS NID_ms_ctl_sign R_PUBLIC_KEY_IS_NOT_RSA XN_FLAG_SEP_CPLUS_SPC NID_ms_efs R_READ_WRONG_PACKET_TYPE XN_FLAG_SEP_MASK NID_ms_ext_req R_SHORT_READ XN_FLAG_SEP_MULTILINE NID_ms_sgc R_SSL_SESSION_ID_IS_DIFFERENT XN_FLAG_SEP_SPLUS_SPC NID_name R_UNABLE_TO_EXTRACT_PUBLIC_KEY XN_FLAG_SPC_EQ BIO_eof BIO_f_ssl BIO_free BIO_new BIO_new_file BIO_pending BIO_read BIO_s_mem BIO_wpending BIO_write CTX_free CTX_get_cert_store CTX_new CTX_use_RSAPrivateKey_file CTX_use_certificate_file CTX_v23_new CTX_v2_new CTX_v3_new ERR_error_string ERR_get_error ERR_load_RAND_strings ERR_load_SSL_strings PEM_read_bio_X509_CRL RSA_free RSA_generate_key SESSION SESSION_free SESSION_get_master_key SESSION_new SESSION_print X509_NAME_get_text_by_NID X509_NAME_oneline X509_STORE_CTX_set_flags X509_STORE_add_cert X509_STORE_add_crl X509_check_email X509_check_host X509_check_ip X509_check_ip_asc X509_free X509_get_issuer_name X509_get_subject_name X509_load_cert_crl_file X509_load_cert_file X509_load_crl_file accept add_session clear clear_error connect copy_session_id d2i_SSL_SESSION die_if_ssl_error die_now do_https dump_peer_certificate err flush_sessions free get_cipher get_cipher_list get_client_random get_fd get_http get_http4 get_https get_https3 get_https4 get_httpx get_httpx4 get_peer_certificate get_peer_cert_chain get_rbio get_read_ahead get_server_random get_shared_ciphers get_time get_timeout get_wbio i2d_SSL_SESSION load_error_strings make_form make_headers new peek pending post_http post_http4 post_https post_https3 post_https4 post_httpx post_httpx4 print_errs read remove_session rstate_string rstate_string_long set_bio set_cert_and_key set_cipher_list set_fd set_read_ahead set_rfd set_server_cert_and_key set_session set_time set_timeout set_verify set_wfd ssl_read_CRLF ssl_read_all ssl_read_until ssl_write_CRLF ssl_write_all sslcat state_string state_string_long tcp_read_CRLF tcp_read_all tcp_read_until tcp_write_CRLF tcp_write_all tcpcat tcpxcat use_PrivateKey use_PrivateKey_ASN1 use_PrivateKey_file use_RSAPrivateKey use_RSAPrivateKey_ASN1 use_RSAPrivateKey_file use_certificate use_certificate_ASN1 use_certificate_file write d2i_OCSP_RESPONSE i2d_OCSP_RESPONSE OCSP_RESPONSE_free d2i_OCSP_REQUEST i2d_OCSP_REQUEST OCSP_REQUEST_free OCSP_cert2ids OCSP_ids2req OCSP_response_status OCSP_response_status_str OCSP_response_verify OCSP_response_results OCSP_RESPONSE_STATUS_INTERNALERROR OCSP_RESPONSE_STATUS_MALFORMEDREQUEST OCSP_RESPONSE_STATUS_SIGREQUIRED OCSP_RESPONSE_STATUS_SUCCESSFUL OCSP_RESPONSE_STATUS_TRYLATER OCSP_RESPONSE_STATUS_UNAUTHORIZED TLSEXT_STATUSTYPE_ocsp V_OCSP_CERTSTATUS_GOOD V_OCSP_CERTSTATUS_REVOKED V_OCSP_CERTSTATUS_UNKNOWN ); sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant() # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. my $constname; ($constname = $AUTOLOAD) =~ s/.*:://; my $val = constant($constname); if ($! != 0) { if ($! =~ /((Invalid)|(not valid))/i || $!{EINVAL}) { $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } else { croak "Your vendor has not defined SSLeay macro $constname"; } } eval "sub $AUTOLOAD { $val }"; goto &$AUTOLOAD; } eval { require XSLoader; XSLoader::load('Net::SSLeay', $VERSION); 1; } or do { require DynaLoader; push @ISA, 'DynaLoader'; bootstrap Net::SSLeay $VERSION; }; # Preloaded methods go here. $CRLF = "\x0d\x0a"; # because \r\n is not fully portable ### Print SSLeay error stack sub print_errs { my ($msg) = @_; my ($count, $err, $errs, $e) = (0,0,''); while ($err = ERR_get_error()) { $count ++; $e = "$msg $$: $count - " . ERR_error_string($err) . "\n"; $errs .= $e; warn $e if $Net::SSLeay::trace; } return $errs; } # Death is conditional to SSLeay errors existing, i.e. this function checks # for errors and only dies in affirmative. # usage: Net::SSLeay::write($ssl, "foo") or die_if_ssl_error("SSL write ($!)"); sub die_if_ssl_error { my ($msg) = @_; die "$$: $msg\n" if print_errs($msg); } # Unconditional death. Used to print SSLeay errors before dying. # usage: Net::SSLeay::connect($ssl) or die_now("Failed SSL connect ($!)"); sub die_now { my ($msg) = @_; print_errs($msg); die "$$: $msg\n"; } # Perl 5.6.* unicode support causes that length() no longer reliably # reflects the byte length of a string. This eval is to fix that. # Thanks to Sean Burke for the snippet. BEGIN{ eval 'use bytes; sub blength ($) { defined $_[0] ? length $_[0] : 0 }'; $@ and eval ' sub blength ($) { defined $_[0] ? length $_[0] : 0 }' ; } # Autoload methods go after __END__, and are processed by the autosplit program. 1; __END__ ### Some methods that are macros in C sub want_nothing { want(shift) == 1 } sub want_read { want(shift) == 2 } sub want_write { want(shift) == 3 } sub want_X509_lookup { want(shift) == 4 } ### ### Open TCP stream to given host and port, looking up the details ### from system databases or DNS. ### sub open_tcp_connection { my ($dest_serv, $port) = @_; my ($errs); $port = getservbyname($port, 'tcp') unless $port =~ /^\d+$/; my $dest_serv_ip = gethostbyname($dest_serv); unless (defined($dest_serv_ip)) { $errs = "$0 $$: open_tcp_connection: destination host not found:" . " `$dest_serv' (port $port) ($!)\n"; warn $errs if $trace; return wantarray ? (0, $errs) : 0; } my $sin = sockaddr_in($port, $dest_serv_ip); warn "Opening connection to $dest_serv:$port (" . inet_ntoa($dest_serv_ip) . ")" if $trace>2; my $proto = &Socket::IPPROTO_TCP; # getprotobyname('tcp') not available on android if (socket (SSLCAT_S, &PF_INET(), &SOCK_STREAM(), $proto)) { warn "next connect" if $trace>3; if (CORE::connect (SSLCAT_S, $sin)) { my $old_out = select (SSLCAT_S); $| = 1; select ($old_out); warn "connected to $dest_serv, $port" if $trace>3; return wantarray ? (1, undef) : 1; # Success } } $errs = "$0 $$: open_tcp_connection: failed `$dest_serv', $port ($!)\n"; warn $errs if $trace; close SSLCAT_S; return wantarray ? (0, $errs) : 0; # Fail } ### Open connection via standard web proxy, if one was defined ### using set_proxy(). sub open_proxy_tcp_connection { my ($dest_serv, $port) = @_; return open_tcp_connection($dest_serv, $port) if !$proxyhost; warn "Connect via proxy: $proxyhost:$proxyport" if $trace>2; my ($ret, $errs) = open_tcp_connection($proxyhost, $proxyport); return wantarray ? (0, $errs) : 0 if !$ret; # Connection fail warn "Asking proxy to connect to $dest_serv:$port" if $trace>2; #print SSLCAT_S "CONNECT $dest_serv:$port HTTP/1.0$proxyauth$CRLF$CRLF"; #my $line = ; # *** bug? Mixing stdio with syscall read? ($ret, $errs) = tcp_write_all("CONNECT $dest_serv:$port HTTP/1.0$proxyauth$CRLF$CRLF"); return wantarray ? (0,$errs) : 0 if $errs; ($line, $errs) = tcp_read_until($CRLF . $CRLF, 1024); warn "Proxy response: $line" if $trace>2; return wantarray ? (0,$errs) : 0 if $errs; return wantarray ? (1,'') : 1; # Success } ### ### read and write helpers that block ### sub debug_read { my ($replyr, $gotr) = @_; my $vm = $trace>2 && $linux_debug ? (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown'; warn " got " . blength($$gotr) . ':' . blength($$replyr) . " bytes (VM=$vm).\n" if $trace == 3; warn " got `$$gotr' (" . blength($$gotr) . ':' . blength($$replyr) . " bytes, VM=$vm)\n" if $trace>3; } sub ssl_read_all { my ($ssl,$how_much) = @_; $how_much = 2000000000 unless $how_much; my ($got, $rv, $errs); my $reply = ''; while ($how_much > 0) { ($got, $rv) = Net::SSLeay::read($ssl, ($how_much > 32768) ? 32768 : $how_much ); if (! defined $got) { my $err = Net::SSLeay::get_error($ssl, $rv); if ($err != Net::SSLeay::ERROR_WANT_READ() and $err != Net::SSLeay::ERROR_WANT_WRITE()) { $errs = print_errs('SSL_read'); last; } next; } $how_much -= blength($got); debug_read(\$reply, \$got) if $trace>1; last if $got eq ''; # EOF $reply .= $got; } return wantarray ? ($reply, $errs) : $reply; } sub tcp_read_all { my ($how_much) = @_; $how_much = 2000000000 unless $how_much; my ($n, $got, $errs); my $reply = ''; my $bsize = 0x10000; while ($how_much > 0) { $n = sysread(SSLCAT_S,$got, (($bsize < $how_much) ? $bsize : $how_much)); warn "Read error: $! ($n,$how_much)" unless defined $n; last if !$n; # EOF $how_much -= $n; debug_read(\$reply, \$got) if $trace>1; $reply .= $got; } return wantarray ? ($reply, $errs) : $reply; } sub ssl_write_all { my $ssl = $_[0]; my ($data_ref, $errs); if (ref $_[1]) { $data_ref = $_[1]; } else { $data_ref = \$_[1]; } my ($wrote, $written, $to_write) = (0,0, blength($$data_ref)); my $vm = $trace>2 && $linux_debug ? (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown'; warn " write_all VM at entry=$vm\n" if $trace>2; while ($to_write) { #sleep 1; # *** DEBUG warn "partial `$$data_ref'\n" if $trace>3; $wrote = write_partial($ssl, $written, $to_write, $$data_ref); if (defined $wrote && ($wrote > 0)) { # write_partial can return -1 $written += $wrote; $to_write -= $wrote; } else { if (defined $wrote) { # check error conditions via SSL_get_error per man page if ( my $sslerr = get_error($ssl, $wrote) ) { my $errstr = ERR_error_string($sslerr); my $errname = ''; SWITCH: { $sslerr == constant("ERROR_NONE") && do { # according to map page SSL_get_error(3ssl): # The TLS/SSL I/O operation completed. # This result code is returned if and only if ret > 0 # so if we received it here complain... warn "ERROR_NONE unexpected with invalid return value!" if $trace; $errname = "SSL_ERROR_NONE"; }; $sslerr == constant("ERROR_WANT_READ") && do { # operation did not complete, call again later, so do not # set errname and empty err_que since this is a known # error that is expected but, we should continue to try # writing the rest of our data with same io call and params. warn "ERROR_WANT_READ (TLS/SSL Handshake, will continue)\n" if $trace; print_errs('SSL_write(want read)'); last SWITCH; }; $sslerr == constant("ERROR_WANT_WRITE") && do { # operation did not complete, call again later, so do not # set errname and empty err_que since this is a known # error that is expected but, we should continue to try # writing the rest of our data with same io call and params. warn "ERROR_WANT_WRITE (TLS/SSL Handshake, will continue)\n" if $trace; print_errs('SSL_write(want write)'); last SWITCH; }; $sslerr == constant("ERROR_ZERO_RETURN") && do { # valid protocol closure from other side, no longer able to # write, since there is no longer a session... warn "ERROR_ZERO_RETURN($wrote): TLS/SSLv3 Closure alert\n" if $trace; $errname = "SSL_ERROR_ZERO_RETURN"; last SWITCH; }; $sslerr == constant("ERROR_SSL") && do { # library/protocol error warn "ERROR_SSL($wrote): Library/Protocol error occured\n" if $trace; $errname = "SSL_ERROR_SSL"; last SWITCH; }; $sslerr == constant("ERROR_WANT_CONNECT") && do { # according to man page, should never happen on call to # SSL_write, so complain, but handle as known error type warn "ERROR_WANT_CONNECT: Unexpected error for SSL_write\n" if $trace; $errname = "SSL_ERROR_WANT_CONNECT"; last SWITCH; }; $sslerr == constant("ERROR_WANT_ACCEPT") && do { # according to man page, should never happen on call to # SSL_write, so complain, but handle as known error type warn "ERROR_WANT_ACCEPT: Unexpected error for SSL_write\n" if $trace; $errname = "SSL_ERROR_WANT_ACCEPT"; last SWITCH; }; $sslerr == constant("ERROR_WANT_X509_LOOKUP") && do { # operation did not complete: waiting on call back, # call again later, so do not set errname and empty err_que # since this is a known error that is expected but, we should # continue to try writing the rest of our data with same io # call parameter. warn "ERROR_WANT_X509_LOOKUP: (Cert Callback asked for in ". "SSL_write will contine)\n" if $trace; print_errs('SSL_write(want x509'); last SWITCH; }; $sslerr == constant("ERROR_SYSCALL") && do { # some IO error occured. According to man page: # Check retval, ERR, fallback to errno if ($wrote==0) { # EOF warn "ERROR_SYSCALL($wrote): EOF violates protocol.\n" if $trace; $errname = "SSL_ERROR_SYSCALL(EOF)"; } else { # -1 underlying BIO error reported. # check error que for details, don't set errname since we # are directly appending to errs my $chkerrs = print_errs('SSL_write (syscall)'); if ($chkerrs) { warn "ERROR_SYSCALL($wrote): Have errors\n" if $trace; $errs .= "ssl_write_all $$: 1 - ERROR_SYSCALL($wrote,". "$sslerr,$errstr,$!)\n$chkerrs"; } else { # que was empty, use errno warn "ERROR_SYSCALL($wrote): errno($!)\n" if $trace; $errs .= "ssl_write_all $$: 1 - ERROR_SYSCALL($wrote,". "$sslerr) : $!\n"; } } last SWITCH; }; warn "Unhandled val $sslerr from SSL_get_error(SSL,$wrote)\n" if $trace; $errname = "SSL_ERROR_?($sslerr)"; } # end of SWITCH block if ($errname) { # if we had an errname set add the error $errs .= "ssl_write_all $$: 1 - $errname($wrote,$sslerr,". "$errstr,$!)\n"; } } # endif on have SSL_get_error val } # endif on $wrote defined } # endelse on $wrote > 0 $vm = $trace>2 && $linux_debug ? (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown'; warn " written so far $wrote:$written bytes (VM=$vm)\n" if $trace>2; # append remaining errors in que and report if errs exist $errs .= print_errs('SSL_write'); return (wantarray ? (undef, $errs) : undef) if $errs; } return wantarray ? ($written, $errs) : $written; } sub tcp_write_all { my ($data_ref, $errs); if (ref $_[0]) { $data_ref = $_[0]; } else { $data_ref = \$_[0]; } my ($wrote, $written, $to_write) = (0,0, blength($$data_ref)); my $vm = $trace>2 && $linux_debug ? (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown'; warn " write_all VM at entry=$vm to_write=$to_write\n" if $trace>2; while ($to_write) { warn "partial `$$data_ref'\n" if $trace>3; $wrote = syswrite(SSLCAT_S, $$data_ref, $to_write, $written); if (defined $wrote && ($wrote > 0)) { # write_partial can return -1 $written += $wrote; $to_write -= $wrote; } elsif (!defined($wrote)) { warn "tcp_write_all: $!"; return (wantarray ? (undef, "$!") : undef); } $vm = $trace>2 && $linux_debug ? (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown'; warn " written so far $wrote:$written bytes (VM=$vm)\n" if $trace>2; } return wantarray ? ($written, '') : $written; } ### from patch by Clinton Wong # ssl_read_until($ssl [, $delimit [, $max_length]]) # if $delimit missing, use $/ if it exists, otherwise use \n # read until delimiter reached, up to $max_length chars if defined sub ssl_read_until ($;$$) { my ($ssl,$delim, $max_length) = @_; # guess the delim string if missing if ( ! defined $delim ) { if ( defined $/ && length $/ ) { $delim = $/ } else { $delim = "\n" } # Note: \n,$/ value depends on the platform } my $len_delim = length $delim; my ($got); my $reply = ''; # If we have OpenSSL 0.9.6a or later, we can use SSL_peek to # speed things up. # N.B. 0.9.6a has security problems, so the support for # anything earlier than 0.9.6e will be dropped soon. if (&Net::SSLeay::OPENSSL_VERSION_NUMBER >= 0x0090601f) { $max_length = 2000000000 unless (defined $max_length); my ($pending, $peek_length, $found, $done); while (blength($reply) < $max_length and !$done) { #Block if necessary until we get some data $got = Net::SSLeay::peek($ssl,1); last if print_errs('SSL_peek'); $pending = Net::SSLeay::pending($ssl) + blength($reply); $peek_length = ($pending > $max_length) ? $max_length : $pending; $peek_length -= blength($reply); $got = Net::SSLeay::peek($ssl, $peek_length); last if print_errs('SSL_peek'); $peek_length = blength($got); #$found = index($got, $delim); # Old and broken # the delimiter may be split across two gets, so we prepend # a little from the last get onto this one before we check # for a match my $match; if(blength($reply) >= blength($delim) - 1) { #if what we've read so far is greater or equal #in length of what we need to prepatch $match = substr $reply, blength($reply) - blength($delim) + 1; } else { $match = $reply; } $match .= $got; $found = index($match, $delim); if ($found > -1) { #$got = Net::SSLeay::ssl_read_all($ssl, $found+$len_delim); #read up to the end of the delimiter $got = Net::SSLeay::ssl_read_all($ssl, $found + $len_delim - ((blength($match)) - (blength($got)))); $done = 1; } else { $got = Net::SSLeay::ssl_read_all($ssl, $peek_length); $done = 1 if ($peek_length == $max_length - blength($reply)); } last if print_errs('SSL_read'); debug_read(\$reply, \$got) if $trace>1; last if $got eq ''; $reply .= $got; } } else { while (!defined $max_length || length $reply < $max_length) { $got = Net::SSLeay::ssl_read_all($ssl,1); # one by one last if print_errs('SSL_read'); debug_read(\$reply, \$got) if $trace>1; last if $got eq ''; $reply .= $got; last if $len_delim && substr($reply, blength($reply)-$len_delim) eq $delim; } } return $reply; } sub tcp_read_until { my ($delim, $max_length) = @_; # guess the delim string if missing if ( ! defined $delim ) { if ( defined $/ && length $/ ) { $delim = $/ } else { $delim = "\n" } # Note: \n,$/ value depends on the platform } my $len_delim = length $delim; my ($n,$got); my $reply = ''; while (!defined $max_length || length $reply < $max_length) { $n = sysread(SSLCAT_S, $got, 1); # one by one warn "tcp_read_until: $!" if !defined $n; debug_read(\$reply, \$got) if $trace>1; last if !$n; # EOF $reply .= $got; last if $len_delim && substr($reply, blength($reply)-$len_delim) eq $delim; } return $reply; } # ssl_read_CRLF($ssl [, $max_length]) sub ssl_read_CRLF ($;$) { ssl_read_until($_[0], $CRLF, $_[1]) } sub tcp_read_CRLF { tcp_read_until($CRLF, $_[0]) } # ssl_write_CRLF($ssl, $message) writes $message and appends CRLF sub ssl_write_CRLF ($$) { # the next line uses less memory but might use more network packets return ssl_write_all($_[0], $_[1]) + ssl_write_all($_[0], $CRLF); # the next few lines do the same thing at the expense of memory, with # the chance that it will use less packets, since CRLF is in the original # message and won't be sent separately. #my $data_ref; #if (ref $_[1]) { $data_ref = $_[1] } # else { $data_ref = \$_[1] } #my $message = $$data_ref . $CRLF; #return ssl_write_all($_[0], \$message); } sub tcp_write_CRLF { # the next line uses less memory but might use more network packets return tcp_write_all($_[0]) + tcp_write_all($CRLF); # the next few lines do the same thing at the expense of memory, with # the chance that it will use less packets, since CRLF is in the original # message and won't be sent separately. #my $data_ref; #if (ref $_[1]) { $data_ref = $_[1] } # else { $data_ref = \$_[1] } #my $message = $$data_ref . $CRLF; #return tcp_write_all($_[0], \$message); } ### Quickly print out with whom we're talking sub dump_peer_certificate ($) { my ($ssl) = @_; my $cert = get_peer_certificate($ssl); return if print_errs('get_peer_certificate'); print "no cert defined\n" if !defined($cert); # Cipher=NONE with empty cert fix if (!defined($cert) || ($cert == 0)) { warn "cert = `$cert'\n" if $trace; return "Subject Name: undefined\nIssuer Name: undefined\n"; } else { my $x = 'Subject Name: ' . X509_NAME_oneline(X509_get_subject_name($cert)) . "\n" . 'Issuer Name: ' . X509_NAME_oneline(X509_get_issuer_name($cert)) . "\n"; Net::SSLeay::X509_free($cert); return $x; } } ### Arrange some randomness for eay PRNG sub randomize (;$$$) { my ($rn_seed_file, $seed, $egd_path) = @_; my $rnsf = defined($rn_seed_file) && -r $rn_seed_file; $egd_path = ''; $egd_path = $ENV{'EGD_PATH'} if $ENV{'EGD_PATH'}; RAND_seed(rand() + $$); # Stir it with time and pid unless ($rnsf || -r $Net::SSLeay::random_device || $seed || -S $egd_path) { my $poll_retval = Net::SSLeay::RAND_poll(); warn "Random number generator not seeded!!!" if $trace && !$poll_retval; } RAND_load_file($rn_seed_file, -s _) if $rnsf; RAND_seed($seed) if $seed; RAND_seed($ENV{RND_SEED}) if $ENV{RND_SEED}; RAND_load_file($Net::SSLeay::random_device, $Net::SSLeay::how_random/8) if -r $Net::SSLeay::random_device; } sub new_x_ctx { if ($ssl_version == 2) { unless (exists &Net::SSLeay::CTX_v2_new) { warn "ssl_version has been set to 2, but this version of OpenSSL has been compiled without SSLv2 support"; return undef; } $ctx = CTX_v2_new(); } elsif ($ssl_version == 3) { $ctx = CTX_v3_new(); } elsif ($ssl_version == 10) { $ctx = CTX_tlsv1_new(); } elsif ($ssl_version == 11) { unless (exists &Net::SSLeay::CTX_tlsv1_1_new) { warn "ssl_version has been set to 11, but this version of OpenSSL has been compiled without TLSv1.1 support"; return undef; } $ctx = CTX_tlsv1_1_new; } elsif ($ssl_version == 12) { unless (exists &Net::SSLeay::CTX_tlsv1_2_new) { warn "ssl_version has been set to 12, but this version of OpenSSL has been compiled without TLSv1.2 support"; return undef; } $ctx = CTX_tlsv1_2_new; } elsif ($ssl_version == 13) { unless (eval { Net::SSLeay::TLS1_3_VERSION(); } ) { warn "ssl_version has been set to 13, but this version of OpenSSL has been compiled without TLSv1.3 support"; return undef; } $ctx = CTX_new(); unless(Net::SSLeay::CTX_set_min_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION())) { warn "CTX_set_min_proto failed for TLSv1.3"; return undef; } unless(Net::SSLeay::CTX_set_max_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION())) { warn "CTX_set_max_proto failed for TLSv1.3"; return undef; } } else { $ctx = CTX_new(); } return $ctx; } ### ### Standard initialisation. Initialise the ssl library in the usual way ### at most once. Override this if you need differnet initialisation ### SSLeay_add_ssl_algorithms is also protected against multiple runs in SSLeay.xs ### and is also mutex protected in threading perls ### my $library_initialised; sub initialize { if (!$library_initialised) { load_error_strings(); # Some bloat, but I'm after ease of use SSLeay_add_ssl_algorithms(); # and debuggability. randomize(); $library_initialised++; } } ### ### Basic request - response primitive (don't use for https) ### sub sslcat { # address, port, message, $crt, $key --> reply / (reply,errs,cert) my ($dest_serv, $port, $out_message, $crt_path, $key_path) = @_; my ($ctx, $ssl, $got, $errs, $written); ($got, $errs) = open_proxy_tcp_connection($dest_serv, $port); return (wantarray ? (undef, $errs) : undef) unless $got; ### Do SSL negotiation stuff warn "Creating SSL $ssl_version context...\n" if $trace>2; initialize(); # Will init at most once $ctx = new_x_ctx(); goto cleanup2 if $errs = print_errs('CTX_new') or !$ctx; CTX_set_options($ctx, &OP_ALL); goto cleanup2 if $errs = print_errs('CTX_set_options'); warn "Cert `$crt_path' given without key" if $crt_path && !$key_path; set_cert_and_key($ctx, $crt_path, $key_path) if $crt_path; warn "Creating SSL connection (context was '$ctx')...\n" if $trace>2; $ssl = new($ctx); goto cleanup if $errs = print_errs('SSL_new') or !$ssl; warn "Setting fd (ctx $ctx, con $ssl)...\n" if $trace>2; set_fd($ssl, fileno(SSLCAT_S)); goto cleanup if $errs = print_errs('set_fd'); warn "Entering SSL negotiation phase...\n" if $trace>2; if ($trace>2) { my $i = 0; my $p = ''; my $cipher_list = 'Cipher list: '; $p=Net::SSLeay::get_cipher_list($ssl,$i); $cipher_list .= $p if $p; do { $i++; $cipher_list .= ', ' . $p if $p; $p=Net::SSLeay::get_cipher_list($ssl,$i); } while $p; $cipher_list .= '\n'; warn $cipher_list; } $got = Net::SSLeay::connect($ssl); warn "SSLeay connect returned $got\n" if $trace>2; goto cleanup if $errs = print_errs('SSL_connect'); my $server_cert = get_peer_certificate($ssl); print_errs('get_peer_certificate'); if ($trace>1) { warn "Cipher `" . get_cipher($ssl) . "'\n"; print_errs('get_ciper'); warn dump_peer_certificate($ssl); } ### Connected. Exchange some data (doing repeated tries if necessary). warn "sslcat $$: sending " . blength($out_message) . " bytes...\n" if $trace==3; warn "sslcat $$: sending `$out_message' (" . blength($out_message) . " bytes)...\n" if $trace>3; ($written, $errs) = ssl_write_all($ssl, $out_message); goto cleanup unless $written; sleep $slowly if $slowly; # Closing too soon can abort broken servers CORE::shutdown SSLCAT_S, 1; # Half close --> No more output, send EOF to server warn "waiting for reply...\n" if $trace>2; ($got, $errs) = ssl_read_all($ssl); warn "Got " . blength($got) . " bytes.\n" if $trace==3; warn "Got `$got' (" . blength($got) . " bytes)\n" if $trace>3; cleanup: free ($ssl); $errs .= print_errs('SSL_free'); cleanup2: CTX_free ($ctx); $errs .= print_errs('CTX_free'); close SSLCAT_S; return wantarray ? ($got, $errs, $server_cert) : $got; } sub tcpcat { # address, port, message, $crt, $key --> reply / (reply,errs,cert) my ($dest_serv, $port, $out_message) = @_; my ($got, $errs, $written); ($got, $errs) = open_proxy_tcp_connection($dest_serv, $port); return (wantarray ? (undef, $errs) : undef) unless $got; ### Connected. Exchange some data (doing repeated tries if necessary). warn "tcpcat $$: sending " . blength($out_message) . " bytes...\n" if $trace==3; warn "tcpcat $$: sending `$out_message' (" . blength($out_message) . " bytes)...\n" if $trace>3; ($written, $errs) = tcp_write_all($out_message); goto cleanup unless $written; sleep $slowly if $slowly; # Closing too soon can abort broken servers CORE::shutdown SSLCAT_S, 1; # Half close --> No more output, send EOF to server warn "waiting for reply...\n" if $trace>2; ($got, $errs) = tcp_read_all(); warn "Got " . blength($got) . " bytes.\n" if $trace==3; warn "Got `$got' (" . blength($got) . " bytes)\n" if $trace>3; cleanup: close SSLCAT_S; return wantarray ? ($got, $errs) : $got; } sub tcpxcat { my ($usessl, $site, $port, $req, $crt_path, $key_path) = @_; if ($usessl) { return sslcat($site, $port, $req, $crt_path, $key_path); } else { return tcpcat($site, $port, $req); } } ### ### Basic request - response primitive, this is different from sslcat ### because this does not shutdown the connection. ### sub https_cat { # address, port, message --> returns reply / (reply,errs,cert) my ($dest_serv, $port, $out_message, $crt_path, $key_path) = @_; my ($ctx, $ssl, $got, $errs, $written); ($got, $errs) = open_proxy_tcp_connection($dest_serv, $port); return (wantarray ? (undef, $errs) : undef) unless $got; ### Do SSL negotiation stuff warn "Creating SSL $ssl_version context...\n" if $trace>2; initialize(); $ctx = new_x_ctx(); goto cleanup2 if $errs = print_errs('CTX_new') or !$ctx; CTX_set_options($ctx, &OP_ALL); goto cleanup2 if $errs = print_errs('CTX_set_options'); warn "Cert `$crt_path' given without key" if $crt_path && !$key_path; set_cert_and_key($ctx, $crt_path, $key_path) if $crt_path; warn "Creating SSL connection (context was '$ctx')...\n" if $trace>2; $ssl = new($ctx); goto cleanup if $errs = print_errs('SSL_new') or !$ssl; warn "Setting fd (ctx $ctx, con $ssl)...\n" if $trace>2; set_fd($ssl, fileno(SSLCAT_S)); goto cleanup if $errs = print_errs('set_fd'); warn "Entering SSL negotiation phase...\n" if $trace>2; if ($trace>2) { my $i = 0; my $p = ''; my $cipher_list = 'Cipher list: '; $p=Net::SSLeay::get_cipher_list($ssl,$i); $cipher_list .= $p if $p; do { $i++; $cipher_list .= ', ' . $p if $p; $p=Net::SSLeay::get_cipher_list($ssl,$i); } while $p; $cipher_list .= '\n'; warn $cipher_list; } $got = Net::SSLeay::connect($ssl); warn "SSLeay connect failed" if $trace>2 && $got==0; goto cleanup if $errs = print_errs('SSL_connect'); my $server_cert = get_peer_certificate($ssl); print_errs('get_peer_certificate'); if ($trace>1) { warn "Cipher `" . get_cipher($ssl) . "'\n"; print_errs('get_ciper'); warn dump_peer_certificate($ssl); } ### Connected. Exchange some data (doing repeated tries if necessary). warn "https_cat $$: sending " . blength($out_message) . " bytes...\n" if $trace==3; warn "https_cat $$: sending `$out_message' (" . blength($out_message) . " bytes)...\n" if $trace>3; ($written, $errs) = ssl_write_all($ssl, $out_message); goto cleanup unless $written; warn "waiting for reply...\n" if $trace>2; ($got, $errs) = ssl_read_all($ssl); warn "Got " . blength($got) . " bytes.\n" if $trace==3; warn "Got `$got' (" . blength($got) . " bytes)\n" if $trace>3; cleanup: free ($ssl); $errs .= print_errs('SSL_free'); cleanup2: CTX_free ($ctx); $errs .= print_errs('CTX_free'); close SSLCAT_S; return wantarray ? ($got, $errs, $server_cert) : $got; } sub http_cat { # address, port, message --> returns reply / (reply,errs,cert) my ($dest_serv, $port, $out_message) = @_; my ($got, $errs, $written); ($got, $errs) = open_proxy_tcp_connection($dest_serv, $port); return (wantarray ? (undef, $errs) : undef) unless $got; ### Connected. Exchange some data (doing repeated tries if necessary). warn "http_cat $$: sending " . blength($out_message) . " bytes...\n" if $trace==3; warn "http_cat $$: sending `$out_message' (" . blength($out_message) . " bytes)...\n" if $trace>3; ($written, $errs) = tcp_write_all($out_message); goto cleanup unless $written; warn "waiting for reply...\n" if $trace>2; ($got, $errs) = tcp_read_all(); warn "Got " . blength($got) . " bytes.\n" if $trace==3; warn "Got `$got' (" . blength($got) . " bytes)\n" if $trace>3; cleanup: close SSLCAT_S; return wantarray ? ($got, $errs) : $got; } sub httpx_cat { my ($usessl, $site, $port, $req, $crt_path, $key_path) = @_; warn "httpx_cat: usessl=$usessl ($site:$port)" if $trace; if ($usessl) { return https_cat($site, $port, $req, $crt_path, $key_path); } else { return http_cat($site, $port, $req); } } ### ### Easy set up of private key and certificate ### sub set_cert_and_key ($$$) { my ($ctx, $cert_path, $key_path) = @_; my $errs = ''; # Following will ask password unless private key is not encrypted CTX_use_PrivateKey_file( $ctx, $key_path, &FILETYPE_PEM ) == 1 or $errs .= print_errs("private key `$key_path' ($!)"); CTX_use_certificate_file ($ctx, $cert_path, &FILETYPE_PEM) == 1 or $errs .= print_errs("certificate `$cert_path' ($!)"); return wantarray ? (undef, $errs) : ($errs eq ''); } ### Old deprecated API sub set_server_cert_and_key ($$$) { &set_cert_and_key } ### Set up to use web proxy sub set_proxy ($$;**) { ($proxyhost, $proxyport, $proxyuser, $proxypass) = @_; require MIME::Base64 if $proxyuser; $proxyauth = $proxyuser ? $CRLF . 'Proxy-authorization: Basic ' . MIME::Base64::encode("$proxyuser:$proxypass", '') : ''; } ### ### Easy https manipulation routines ### sub make_form { my (@fields) = @_; my $form; while (@fields) { my ($name, $data) = (shift(@fields), shift(@fields)); $data =~ s/([^\w\-.\@\$ ])/sprintf("%%%2.2x",ord($1))/gse; $data =~ tr[ ][+]; $form .= "$name=$data&"; } chop $form; return $form; } sub make_headers { my (@headers) = @_; my $headers; while (@headers) { my $header = shift(@headers); my $value = shift(@headers); $header =~ s/:$//; $value =~ s/\x0d?\x0a$//; # because we add it soon, see below $headers .= "$header: $value$CRLF"; } return $headers; } sub do_httpx3 { my ($method, $usessl, $site, $port, $path, $headers, $content, $mime_type, $crt_path, $key_path) = @_; my ($response, $page, $h,$v); my $len = blength($content); if ($len) { $mime_type = "application/x-www-form-urlencoded" unless $mime_type; $content = "Content-Type: $mime_type$CRLF" . "Content-Length: $len$CRLF$CRLF$content"; } else { $content = "$CRLF$CRLF"; } my $req = "$method $path HTTP/1.0$CRLF"; unless (defined $headers && $headers =~ /^Host:/m) { $req .= "Host: $site"; unless (($port == 80 && !$usessl) || ($port == 443 && $usessl)) { $req .= ":$port"; } $req .= $CRLF; } $req .= (defined $headers ? $headers : '') . "Accept: */*$CRLF$content"; warn "do_httpx3($method,$usessl,$site:$port)" if $trace; my ($http, $errs, $server_cert) = httpx_cat($usessl, $site, $port, $req, $crt_path, $key_path); return (undef, "HTTP/1.0 900 NET OR SSL ERROR$CRLF$CRLF$errs") if $errs; $http = '' if !defined $http; ($headers, $page) = split /\s?\n\s?\n/, $http, 2; warn "headers >$headers< page >>$page<< http >>>$http<<<" if $trace>1; ($response, $headers) = split /\s?\n/, $headers, 2; return ($page, $response, $headers, $server_cert); } sub do_https3 { splice(@_,1,0) = 1; do_httpx3; } # Legacy undocumented ### do_https2() is a legacy version in the sense that it is unable ### to return all instances of duplicate headers. sub do_httpx2 { my ($page, $response, $headers, $server_cert) = &do_httpx3; X509_free($server_cert) if defined $server_cert; return ($page, $response, defined $headers ? map( { ($h,$v)=/^(\S+)\:\s*(.*)$/; (uc($h),$v); } split(/\s?\n/, $headers) ) : () ); } sub do_https2 { splice(@_,1,0) = 1; do_httpx2; } # Legacy undocumented ### Returns headers as a hash where multiple instances of same header ### are handled correctly. sub do_httpx4 { my ($page, $response, $headers, $server_cert) = &do_httpx3; my %hr = (); for my $hh (split /\s?\n/, $headers) { my ($h,$v) = ($hh =~ /^(\S+)\:\s*(.*)$/); push @{$hr{uc($h)}}, $v; } return ($page, $response, \%hr, $server_cert); } sub do_https4 { splice(@_,1,0) = 1; do_httpx4; } # Legacy undocumented # https sub get_https { do_httpx2(GET => 1, @_) } sub post_https { do_httpx2(POST => 1, @_) } sub put_https { do_httpx2(PUT => 1, @_) } sub head_https { do_httpx2(HEAD => 1, @_) } sub get_https3 { do_httpx3(GET => 1, @_) } sub post_https3 { do_httpx3(POST => 1, @_) } sub put_https3 { do_httpx3(PUT => 1, @_) } sub head_https3 { do_httpx3(HEAD => 1, @_) } sub get_https4 { do_httpx4(GET => 1, @_) } sub post_https4 { do_httpx4(POST => 1, @_) } sub put_https4 { do_httpx4(PUT => 1, @_) } sub head_https4 { do_httpx4(HEAD => 1, @_) } # http sub get_http { do_httpx2(GET => 0, @_) } sub post_http { do_httpx2(POST => 0, @_) } sub put_http { do_httpx2(PUT => 0, @_) } sub head_http { do_httpx2(HEAD => 0, @_) } sub get_http3 { do_httpx3(GET => 0, @_) } sub post_http3 { do_httpx3(POST => 0, @_) } sub put_http3 { do_httpx3(PUT => 0, @_) } sub head_http3 { do_httpx3(HEAD => 0, @_) } sub get_http4 { do_httpx4(GET => 0, @_) } sub post_http4 { do_httpx4(POST => 0, @_) } sub put_http4 { do_httpx4(PUT => 0, @_) } sub head_http4 { do_httpx4(HEAD => 0, @_) } # Either https or http sub get_httpx { do_httpx2(GET => @_) } sub post_httpx { do_httpx2(POST => @_) } sub put_httpx { do_httpx2(PUT => @_) } sub head_httpx { do_httpx2(HEAD => @_) } sub get_httpx3 { do_httpx3(GET => @_) } sub post_httpx3 { do_httpx3(POST => @_) } sub put_httpx3 { do_httpx3(PUT => @_) } sub head_httpx3 { do_httpx3(HEAD => @_) } sub get_httpx4 { do_httpx4(GET => @_) } sub post_httpx4 { do_httpx4(POST => @_) } sub put_httpx4 { do_httpx4(PUT => @_) } sub head_httpx4 { do_httpx4(HEAD => @_) } ### Legacy, don't use # ($page, $respone_or_err, %headers) = do_https(...); sub do_https { my ($site, $port, $path, $method, $headers, $content, $mime_type, $crt_path, $key_path) = @_; do_https2($method, $site, $port, $path, $headers, $content, $mime_type, $crt_path, $key_path); } 1; __END__ PK f1] SSPOP3.pmnu[# Net::POP3.pm # # Copyright (C) 1995-2004 Graham Barr. All rights reserved. # Copyright (C) 2013-2016 Steve Hay. All rights reserved. # This module is free software; you can redistribute it and/or modify it under # the same terms as Perl itself, i.e. under the terms of either the GNU General # Public License or the Artistic License, as specified in the F file. package Net::POP3; use 5.008001; use strict; use warnings; use Carp; use IO::Socket; use Net::Cmd; use Net::Config; our $VERSION = "3.11"; # Code for detecting if we can use SSL my $ssl_class = eval { require IO::Socket::SSL; # first version with default CA on most platforms no warnings 'numeric'; IO::Socket::SSL->VERSION(2.007); } && 'IO::Socket::SSL'; my $nossl_warn = !$ssl_class && 'To use SSL please install IO::Socket::SSL with version>=2.007'; # Code for detecting if we can use IPv6 my $family_key = 'Domain'; my $inet6_class = eval { require IO::Socket::IP; no warnings 'numeric'; IO::Socket::IP->VERSION(0.25) || die; $family_key = 'Family'; } && 'IO::Socket::IP' || eval { require IO::Socket::INET6; no warnings 'numeric'; IO::Socket::INET6->VERSION(2.62); } && 'IO::Socket::INET6'; sub can_ssl { $ssl_class }; sub can_inet6 { $inet6_class }; our @ISA = ('Net::Cmd', $inet6_class || 'IO::Socket::INET'); sub new { my $self = shift; my $type = ref($self) || $self; my ($host, %arg); if (@_ % 2) { $host = shift; %arg = @_; } else { %arg = @_; $host = delete $arg{Host}; } my $hosts = defined $host ? [$host] : $NetConfig{pop3_hosts}; my $obj; if ($arg{SSL}) { # SSL from start die $nossl_warn if !$ssl_class; $arg{Port} ||= 995; } $arg{Timeout} = 120 if ! defined $arg{Timeout}; foreach my $h (@{$hosts}) { $obj = $type->SUPER::new( PeerAddr => ($host = $h), PeerPort => $arg{Port} || 'pop3(110)', Proto => 'tcp', $family_key => $arg{Domain} || $arg{Family}, LocalAddr => $arg{LocalAddr}, LocalPort => exists($arg{ResvPort}) ? $arg{ResvPort} : $arg{LocalPort}, Timeout => $arg{Timeout}, ) and last; } return unless defined $obj; ${*$obj}{'net_pop3_arg'} = \%arg; ${*$obj}{'net_pop3_host'} = $host; if ($arg{SSL}) { Net::POP3::_SSL->start_SSL($obj,%arg) or return; } $obj->autoflush(1); $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef); unless ($obj->response() == CMD_OK) { $obj->close(); return; } ${*$obj}{'net_pop3_banner'} = $obj->message; $obj; } sub host { my $me = shift; ${*$me}{'net_pop3_host'}; } ## ## We don't want people sending me their passwords when they report problems ## now do we :-) ## sub debug_text { $_[2] =~ /^(pass|rpop)/i ? "$1 ....\n" : $_[2]; } sub login { @_ >= 1 && @_ <= 3 or croak 'usage: $pop3->login( USER, PASS )'; my ($me, $user, $pass) = @_; if (@_ <= 2) { ($user, $pass) = $me->_lookup_credentials($user); } $me->user($user) and $me->pass($pass); } sub starttls { my $self = shift; $ssl_class or die $nossl_warn; $self->_STLS or return; Net::POP3::_SSL->start_SSL($self, %{ ${*$self}{'net_pop3_arg'} }, # (ssl) args given in new @_ # more (ssl) args ) or return; return 1; } sub apop { @_ >= 1 && @_ <= 3 or croak 'usage: $pop3->apop( USER, PASS )'; my ($me, $user, $pass) = @_; my $banner; my $md; if (eval { local $SIG{__DIE__}; require Digest::MD5 }) { $md = Digest::MD5->new(); } elsif (eval { local $SIG{__DIE__}; require MD5 }) { $md = MD5->new(); } else { carp "You need to install Digest::MD5 or MD5 to use the APOP command"; return; } return unless ($banner = (${*$me}{'net_pop3_banner'} =~ /(<.*>)/)[0]); if (@_ <= 2) { ($user, $pass) = $me->_lookup_credentials($user); } $md->add($banner, $pass); return unless ($me->_APOP($user, $md->hexdigest)); $me->_get_mailbox_count(); } sub user { @_ == 2 or croak 'usage: $pop3->user( USER )'; $_[0]->_USER($_[1]) ? 1 : undef; } sub pass { @_ == 2 or croak 'usage: $pop3->pass( PASS )'; my ($me, $pass) = @_; return unless ($me->_PASS($pass)); $me->_get_mailbox_count(); } sub reset { @_ == 1 or croak 'usage: $obj->reset()'; my $me = shift; return 0 unless ($me->_RSET); if (defined ${*$me}{'net_pop3_mail'}) { local $_; foreach (@{${*$me}{'net_pop3_mail'}}) { delete $_->{'net_pop3_deleted'}; } } } sub last { @_ == 1 or croak 'usage: $obj->last()'; return unless $_[0]->_LAST && $_[0]->message =~ /(\d+)/; return $1; } sub top { @_ == 2 || @_ == 3 or croak 'usage: $pop3->top( MSGNUM [, NUMLINES ])'; my $me = shift; return unless $me->_TOP($_[0], $_[1] || 0); $me->read_until_dot; } sub popstat { @_ == 1 or croak 'usage: $pop3->popstat()'; my $me = shift; return () unless $me->_STAT && $me->message =~ /(\d+)\D+(\d+)/; ($1 || 0, $2 || 0); } sub list { @_ == 1 || @_ == 2 or croak 'usage: $pop3->list( [ MSGNUM ] )'; my $me = shift; return unless $me->_LIST(@_); if (@_) { $me->message =~ /\d+\D+(\d+)/; return $1 || undef; } my $info = $me->read_until_dot or return; my %hash = map { (/(\d+)\D+(\d+)/) } @$info; return \%hash; } sub get { @_ == 2 or @_ == 3 or croak 'usage: $pop3->get( MSGNUM [, FH ])'; my $me = shift; return unless $me->_RETR(shift); $me->read_until_dot(@_); } sub getfh { @_ == 2 or croak 'usage: $pop3->getfh( MSGNUM )'; my $me = shift; return unless $me->_RETR(shift); return $me->tied_fh; } sub delete { @_ == 2 or croak 'usage: $pop3->delete( MSGNUM )'; my $me = shift; return 0 unless $me->_DELE(@_); ${*$me}{'net_pop3_deleted'} = 1; } sub uidl { @_ == 1 || @_ == 2 or croak 'usage: $pop3->uidl( [ MSGNUM ] )'; my $me = shift; my $uidl; $me->_UIDL(@_) or return; if (@_) { $uidl = ($me->message =~ /\d+\s+([\041-\176]+)/)[0]; } else { my $ref = $me->read_until_dot or return; $uidl = {}; foreach my $ln (@$ref) { my ($msg, $uid) = $ln =~ /^\s*(\d+)\s+([\041-\176]+)/; $uidl->{$msg} = $uid; } } return $uidl; } sub ping { @_ == 2 or croak 'usage: $pop3->ping( USER )'; my $me = shift; return () unless $me->_PING(@_) && $me->message =~ /(\d+)\D+(\d+)/; ($1 || 0, $2 || 0); } sub _lookup_credentials { my ($me, $user) = @_; require Net::Netrc; $user ||= eval { local $SIG{__DIE__}; (getpwuid($>))[0] } || $ENV{NAME} || $ENV{USER} || $ENV{LOGNAME}; my $m = Net::Netrc->lookup(${*$me}{'net_pop3_host'}, $user); $m ||= Net::Netrc->lookup(${*$me}{'net_pop3_host'}); my $pass = $m ? $m->password || "" : ""; ($user, $pass); } sub _get_mailbox_count { my ($me) = @_; my $ret = ${*$me}{'net_pop3_count'} = ($me->message =~ /(\d+)\s+message/io) ? $1 : ($me->popstat)[0]; $ret ? $ret : "0E0"; } sub _STAT { shift->command('STAT' )->response() == CMD_OK } sub _LIST { shift->command('LIST', @_)->response() == CMD_OK } sub _RETR { shift->command('RETR', $_[0])->response() == CMD_OK } sub _DELE { shift->command('DELE', $_[0])->response() == CMD_OK } sub _NOOP { shift->command('NOOP' )->response() == CMD_OK } sub _RSET { shift->command('RSET' )->response() == CMD_OK } sub _QUIT { shift->command('QUIT' )->response() == CMD_OK } sub _TOP { shift->command( 'TOP', @_)->response() == CMD_OK } sub _UIDL { shift->command('UIDL', @_)->response() == CMD_OK } sub _USER { shift->command('USER', $_[0])->response() == CMD_OK } sub _PASS { shift->command('PASS', $_[0])->response() == CMD_OK } sub _APOP { shift->command('APOP', @_)->response() == CMD_OK } sub _PING { shift->command('PING', $_[0])->response() == CMD_OK } sub _RPOP { shift->command('RPOP', $_[0])->response() == CMD_OK } sub _LAST { shift->command('LAST' )->response() == CMD_OK } sub _CAPA { shift->command('CAPA' )->response() == CMD_OK } sub _STLS { shift->command("STLS", )->response() == CMD_OK } sub quit { my $me = shift; $me->_QUIT; $me->close; } sub DESTROY { my $me = shift; if (defined fileno($me) and ${*$me}{'net_pop3_deleted'}) { $me->reset; $me->quit; } } ## ## POP3 has weird responses, so we emulate them to look the same :-) ## sub response { my $cmd = shift; my $str = $cmd->getline() or return; my $code = "500"; $cmd->debug_print(0, $str) if ($cmd->debug); if ($str =~ s/^\+OK\s*//io) { $code = "200"; } elsif ($str =~ s/^\+\s*//io) { $code = "300"; } else { $str =~ s/^-ERR\s*//io; } ${*$cmd}{'net_cmd_resp'} = [$str]; ${*$cmd}{'net_cmd_code'} = $code; substr($code, 0, 1); } sub capa { my $this = shift; my ($capa, %capabilities); # Fake a capability here $capabilities{APOP} = '' if ($this->banner() =~ /<.*>/); if ($this->_CAPA()) { $capabilities{CAPA} = 1; $capa = $this->read_until_dot(); %capabilities = (%capabilities, map {/^\s*(\S+)\s*(.*)/} @$capa); } else { # Check AUTH for SASL capabilities if ($this->command('AUTH')->response() == CMD_OK) { my $mechanism = $this->read_until_dot(); $capabilities{SASL} = join " ", map {m/([A-Z0-9_-]+)/} @{$mechanism}; } } return ${*$this}{'net_pop3e_capabilities'} = \%capabilities; } sub capabilities { my $this = shift; ${*$this}{'net_pop3e_capabilities'} || $this->capa; } sub auth { my ($self, $username, $password) = @_; eval { require MIME::Base64; require Authen::SASL; } or $self->set_status(500, ["Need MIME::Base64 and Authen::SASL todo auth"]), return 0; my $capa = $self->capa; my $mechanisms = $capa->{SASL} || 'CRAM-MD5'; my $sasl; if (ref($username) and UNIVERSAL::isa($username, 'Authen::SASL')) { $sasl = $username; my $user_mech = $sasl->mechanism || ''; my @user_mech = split(/\s+/, $user_mech); my %user_mech; @user_mech{@user_mech} = (); my @server_mech = split(/\s+/, $mechanisms); my @mech = @user_mech ? grep { exists $user_mech{$_} } @server_mech : @server_mech; unless (@mech) { $self->set_status( 500, [ 'Client SASL mechanisms (', join(', ', @user_mech), ') do not match the SASL mechnism the server announces (', join(', ', @server_mech), ')', ] ); return 0; } $sasl->mechanism(join(" ", @mech)); } else { die "auth(username, password)" if not length $username; $sasl = Authen::SASL->new( mechanism => $mechanisms, callback => { user => $username, pass => $password, authname => $username, } ); } # We should probably allow the user to pass the host, but I don't # currently know and SASL mechanisms that are used by smtp that need it my ($hostname) = split /:/, ${*$self}{'net_pop3_host'}; my $client = eval { $sasl->client_new('pop', $hostname, 0) }; unless ($client) { my $mech = $sasl->mechanism; $self->set_status( 500, [ " Authen::SASL failure: $@", '(please check if your local Authen::SASL installation', "supports mechanism '$mech'" ] ); return 0; } my ($token) = $client->client_start or do { my $mech = $client->mechanism; $self->set_status( 500, [ ' Authen::SASL failure: $client->client_start ', "mechanism '$mech' hostname #$hostname#", $client->error ] ); return 0; }; # We don't support sasl mechanisms that encrypt the socket traffic. # todo that we would really need to change the ISA hierarchy # so we don't inherit from IO::Socket, but instead hold it in an attribute my @cmd = ("AUTH", $client->mechanism); my $code; push @cmd, MIME::Base64::encode_base64($token, '') if defined $token and length $token; while (($code = $self->command(@cmd)->response()) == CMD_MORE) { my ($token) = $client->client_step(MIME::Base64::decode_base64(($self->message)[0])) or do { $self->set_status( 500, [ ' Authen::SASL failure: $client->client_step ', "mechanism '", $client->mechanism, " hostname #$hostname#, ", $client->error ] ); return 0; }; @cmd = (MIME::Base64::encode_base64(defined $token ? $token : '', '')); } $code == CMD_OK; } sub banner { my $this = shift; return ${*$this}{'net_pop3_banner'}; } { package Net::POP3::_SSL; our @ISA = ( $ssl_class ? ($ssl_class):(), 'Net::POP3' ); sub starttls { die "POP3 connection is already in SSL mode" } sub start_SSL { my ($class,$pop3,%arg) = @_; delete @arg{ grep { !m{^SSL_} } keys %arg }; ( $arg{SSL_verifycn_name} ||= $pop3->host ) =~s{(?can_client_sni; $arg{SSL_verifycn_scheme} ||= 'pop3'; my $ok = $class->SUPER::start_SSL($pop3,%arg); $@ = $ssl_class->errstr if !$ok; return $ok; } } 1; __END__ =head1 NAME Net::POP3 - Post Office Protocol 3 Client class (RFC1939) =head1 SYNOPSIS use Net::POP3; # Constructors $pop = Net::POP3->new('pop3host'); $pop = Net::POP3->new('pop3host', Timeout => 60); $pop = Net::POP3->new('pop3host', SSL => 1, Timeout => 60); if ($pop->login($username, $password) > 0) { my $msgnums = $pop->list; # hashref of msgnum => size foreach my $msgnum (keys %$msgnums) { my $msg = $pop->get($msgnum); print @$msg; $pop->delete($msgnum); } } $pop->quit; =head1 DESCRIPTION This module implements a client interface to the POP3 protocol, enabling a perl5 application to talk to POP3 servers. This documentation assumes that you are familiar with the POP3 protocol described in RFC1939. With L installed it also provides support for implicit and explicit TLS encryption, i.e. POP3S or POP3+STARTTLS. A new Net::POP3 object must be created with the I method. Once this has been done, all POP3 commands are accessed via method calls on the object. The Net::POP3 class is a subclass of Net::Cmd and (depending on avaibility) of IO::Socket::IP, IO::Socket::INET6 or IO::Socket::INET. =head1 CONSTRUCTOR =over 4 =item new ( [ HOST ] [, OPTIONS ] ) This is the constructor for a new Net::POP3 object. C is the name of the remote host to which an POP3 connection is required. C is optional. If C is not given then it may instead be passed as the C option described below. If neither is given then the C specified in C will be used. C are passed in a hash like fashion, using key and value pairs. Possible options are: B - POP3 host to connect to. It may be a single scalar, as defined for the C option in L, or a reference to an array with hosts to try in turn. The L method will return the value which was used to connect to the host. B - port to connect to. Default - 110 for plain POP3 and 995 for POP3s (direct SSL). B - If the connection should be done from start with SSL, contrary to later upgrade with C. You can use SSL arguments as documented in L, but it will usually use the right arguments already. B and B - These parameters are passed directly to IO::Socket to allow binding the socket to a specific local address and port. For compatibility with older versions B can be used instead of B. B - This parameter is passed directly to IO::Socket and makes it possible to enforce IPv4 connections even if L is used as super class. Alternatively B can be used. B - Maximum time, in seconds, to wait for a response from the POP3 server (default: 120) B - Enable debugging information =back =head1 METHODS Unless otherwise stated all methods return either a I or I value, with I meaning that the operation was a success. When a method states that it returns a value, failure will be returned as I or an empty list. C inherits from C so methods defined in C may be used to send commands to the remote POP3 server in addition to the methods documented here. =over 4 =item host () Returns the value used by the constructor, and passed to IO::Socket::INET, to connect to the host. =item auth ( USERNAME, PASSWORD ) Attempt SASL authentication. =item user ( USER ) Send the USER command. =item pass ( PASS ) Send the PASS command. Returns the number of messages in the mailbox. =item login ( [ USER [, PASS ]] ) Send both the USER and PASS commands. If C is not given the C uses C to lookup the password using the host and username. If the username is not specified then the current user name will be used. Returns the number of messages in the mailbox. However if there are no messages on the server the string C<"0E0"> will be returned. This is will give a true value in a boolean context, but zero in a numeric context. If there was an error authenticating the user then I will be returned. =item starttls ( SSLARGS ) Upgrade existing plain connection to SSL. You can use SSL arguments as documented in L, but it will usually use the right arguments already. =item apop ( [ USER [, PASS ]] ) Authenticate with the server identifying as C with password C. Similar to L, but the password is not sent in clear text. To use this method you must have the Digest::MD5 or the MD5 module installed, otherwise this method will return I. =item banner () Return the sever's connection banner =item capa () Return a reference to a hash of the capabilities of the server. APOP is added as a pseudo capability. Note that I've been unable to find a list of the standard capability values, and some appear to be multi-word and some are not. We make an attempt at intelligently parsing them, but it may not be correct. =item capabilities () Just like capa, but only uses a cache from the last time we asked the server, so as to avoid asking more than once. =item top ( MSGNUM [, NUMLINES ] ) Get the header and the first C of the body for the message C. Returns a reference to an array which contains the lines of text read from the server. =item list ( [ MSGNUM ] ) If called with an argument the C returns the size of the message in octets. If called without arguments a reference to a hash is returned. The keys will be the C's of all undeleted messages and the values will be their size in octets. =item get ( MSGNUM [, FH ] ) Get the message C from the remote mailbox. If C is not given then get returns a reference to an array which contains the lines of text read from the server. If C is given then the lines returned from the server are printed to the filehandle C. =item getfh ( MSGNUM ) As per get(), but returns a tied filehandle. Reading from this filehandle returns the requested message. The filehandle will return EOF at the end of the message and should not be reused. =item last () Returns the highest C of all the messages accessed. =item popstat () Returns a list of two elements. These are the number of undeleted elements and the size of the mbox in octets. =item ping ( USER ) Returns a list of two elements. These are the number of new messages and the total number of messages for C. =item uidl ( [ MSGNUM ] ) Returns a unique identifier for C if given. If C is not given C returns a reference to a hash where the keys are the message numbers and the values are the unique identifiers. =item delete ( MSGNUM ) Mark message C to be deleted from the remote mailbox. All messages that are marked to be deleted will be removed from the remote mailbox when the server connection closed. =item reset () Reset the status of the remote POP3 server. This includes resetting the status of all messages to not be deleted. =item quit () Quit and close the connection to the remote POP3 server. Any messages marked as deleted will be deleted from the remote mailbox. =item can_inet6 () Returns whether we can use IPv6. =item can_ssl () Returns whether we can use SSL. =back =head1 NOTES If a C object goes out of scope before C method is called then the C method will called before the connection is closed. This means that any messages marked to be deleted will not be. =head1 SEE ALSO L, L, L =head1 AUTHOR Graham Barr EFE. Steve Hay EFE is now maintaining libnet as of version 1.22_02. =head1 COPYRIGHT Copyright (C) 1995-2004 Graham Barr. All rights reserved. Copyright (C) 2013-2016 Steve Hay. All rights reserved. =head1 LICENCE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e. under the terms of either the GNU General Public License or the Artistic License, as specified in the F file. =cut PK f1]c=E HTTP/NB.pmnu[package Net::HTTP::NB; $Net::HTTP::NB::VERSION = '6.17'; use strict; use warnings; use base 'Net::HTTP'; sub can_read { return 1; } sub sysread { my $self = $_[0]; if (${*$self}{'httpnb_read_count'}++) { ${*$self}{'http_buf'} = ${*$self}{'httpnb_save'}; die "Multi-read\n"; } my $buf; my $offset = $_[3] || 0; my $n = sysread($self, $_[1], $_[2], $offset); ${*$self}{'httpnb_save'} .= substr($_[1], $offset); return $n; } sub read_response_headers { my $self = shift; ${*$self}{'httpnb_read_count'} = 0; ${*$self}{'httpnb_save'} = ${*$self}{'http_buf'}; my @h = eval { $self->SUPER::read_response_headers(@_) }; if ($@) { return if $@ eq "Multi-read\n"; die; } return @h; } sub read_entity_body { my $self = shift; ${*$self}{'httpnb_read_count'} = 0; ${*$self}{'httpnb_save'} = ${*$self}{'http_buf'}; # XXX I'm not so sure this does the correct thing in case of # transfer-encoding transforms my $n = eval { $self->SUPER::read_entity_body(@_); }; if ($@) { $_[0] = ""; return -1; } return $n; } 1; =pod =encoding UTF-8 =head1 NAME Net::HTTP::NB - Non-blocking HTTP client =head1 VERSION version 6.17 =head1 SYNOPSIS use Net::HTTP::NB; my $s = Net::HTTP::NB->new(Host => "www.perl.com") || die $@; $s->write_request(GET => "/"); use IO::Select; my $sel = IO::Select->new($s); READ_HEADER: { die "Header timeout" unless $sel->can_read(10); my($code, $mess, %h) = $s->read_response_headers; redo READ_HEADER unless $code; } while (1) { die "Body timeout" unless $sel->can_read(10); my $buf; my $n = $s->read_entity_body($buf, 1024); last unless $n; print $buf; } =head1 DESCRIPTION Same interface as C but it will never try multiple reads when the read_response_headers() or read_entity_body() methods are invoked. This make it possible to multiplex multiple Net::HTTP::NB using select without risk blocking. If read_response_headers() did not see enough data to complete the headers an empty list is returned. If read_entity_body() did not see new entity data in its read the value -1 is returned. =head1 SEE ALSO L =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001-2017 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: Non-blocking HTTP client PK f1]%CCHTTP/Methods.pmnu[package Net::HTTP::Methods; $Net::HTTP::Methods::VERSION = '6.17'; use strict; use warnings; use URI; my $CRLF = "\015\012"; # "\r\n" is not portable *_bytes = defined(&utf8::downgrade) ? sub { unless (utf8::downgrade($_[0], 1)) { require Carp; Carp::croak("Wide character in HTTP request (bytes required)"); } return $_[0]; } : sub { return $_[0]; }; sub new { my $class = shift; unshift(@_, "Host") if @_ == 1; my %cnf = @_; require Symbol; my $self = bless Symbol::gensym(), $class; return $self->http_configure(\%cnf); } sub http_configure { my($self, $cnf) = @_; die "Listen option not allowed" if $cnf->{Listen}; my $explicit_host = (exists $cnf->{Host}); my $host = delete $cnf->{Host}; my $peer = $cnf->{PeerAddr} || $cnf->{PeerHost}; if (!$peer) { die "No Host option provided" unless $host; $cnf->{PeerAddr} = $peer = $host; } # CONNECTIONS # PREFER: port number from PeerAddr, then PeerPort, then http_default_port my $peer_uri = URI->new("http://$peer"); $cnf->{"PeerPort"} = $peer_uri->_port || $cnf->{PeerPort} || $self->http_default_port; $cnf->{"PeerAddr"} = $peer_uri->host; # HOST header: # If specified but blank, ignore. # If specified with a value, add the port number # If not specified, set to PeerAddr and port number # ALWAYS: If IPv6 address, use [brackets] (thanks to the URI package) # ALWAYS: omit port number if http_default_port if (($host) || (! $explicit_host)) { my $uri = ($explicit_host) ? URI->new("http://$host") : $peer_uri->clone; if (!$uri->_port) { # Always use *our* $self->http_default_port instead of URI's (Covers HTTP, HTTPS) $uri->port( $cnf->{PeerPort} || $self->http_default_port); } my $host_port = $uri->host_port; # Returns host:port or [ipv6]:port my $remove = ":" . $self->http_default_port; # we want to remove the default port number if (substr($host_port,0-length($remove)) eq $remove) { substr($host_port,0-length($remove)) = ""; } $host = $host_port; } $cnf->{Proto} = 'tcp'; my $keep_alive = delete $cnf->{KeepAlive}; my $http_version = delete $cnf->{HTTPVersion}; $http_version = "1.1" unless defined $http_version; my $peer_http_version = delete $cnf->{PeerHTTPVersion}; $peer_http_version = "1.0" unless defined $peer_http_version; my $send_te = delete $cnf->{SendTE}; my $max_line_length = delete $cnf->{MaxLineLength}; $max_line_length = 8*1024 unless defined $max_line_length; my $max_header_lines = delete $cnf->{MaxHeaderLines}; $max_header_lines = 128 unless defined $max_header_lines; return undef unless $self->http_connect($cnf); $self->host($host); $self->keep_alive($keep_alive); $self->send_te($send_te); $self->http_version($http_version); $self->peer_http_version($peer_http_version); $self->max_line_length($max_line_length); $self->max_header_lines($max_header_lines); ${*$self}{'http_buf'} = ""; return $self; } sub http_default_port { 80; } # set up property accessors for my $method (qw(host keep_alive send_te max_line_length max_header_lines peer_http_version)) { my $prop_name = "http_" . $method; no strict 'refs'; *$method = sub { my $self = shift; my $old = ${*$self}{$prop_name}; ${*$self}{$prop_name} = shift if @_; return $old; }; } # we want this one to be a bit smarter sub http_version { my $self = shift; my $old = ${*$self}{'http_version'}; if (@_) { my $v = shift; $v = "1.0" if $v eq "1"; # float unless ($v eq "1.0" or $v eq "1.1") { require Carp; Carp::croak("Unsupported HTTP version '$v'"); } ${*$self}{'http_version'} = $v; } $old; } sub format_request { my $self = shift; my $method = shift; my $uri = shift; my $content = (@_ % 2) ? pop : ""; for ($method, $uri) { require Carp; Carp::croak("Bad method or uri") if /\s/ || !length; } push(@{${*$self}{'http_request_method'}}, $method); my $ver = ${*$self}{'http_version'}; my $peer_ver = ${*$self}{'http_peer_http_version'} || "1.0"; my @h; my @connection; my %given = (host => 0, "content-length" => 0, "te" => 0); while (@_) { my($k, $v) = splice(@_, 0, 2); my $lc_k = lc($k); if ($lc_k eq "connection") { $v =~ s/^\s+//; $v =~ s/\s+$//; push(@connection, split(/\s*,\s*/, $v)); next; } if (exists $given{$lc_k}) { $given{$lc_k}++; } push(@h, "$k: $v"); } if (length($content) && !$given{'content-length'}) { push(@h, "Content-Length: " . length($content)); } my @h2; if ($given{te}) { push(@connection, "TE") unless grep lc($_) eq "te", @connection; } elsif ($self->send_te && gunzip_ok()) { # gzip is less wanted since the IO::Uncompress::Gunzip interface for # it does not really allow chunked decoding to take place easily. push(@h2, "TE: deflate,gzip;q=0.3"); push(@connection, "TE"); } unless (grep lc($_) eq "close", @connection) { if ($self->keep_alive) { if ($peer_ver eq "1.0") { # from looking at Netscape's headers push(@h2, "Keep-Alive: 300"); unshift(@connection, "Keep-Alive"); } } else { push(@connection, "close") if $ver ge "1.1"; } } push(@h2, "Connection: " . join(", ", @connection)) if @connection; unless ($given{host}) { my $h = ${*$self}{'http_host'}; push(@h2, "Host: $h") if $h; } return _bytes(join($CRLF, "$method $uri HTTP/$ver", @h2, @h, "", $content)); } sub write_request { my $self = shift; $self->print($self->format_request(@_)); } sub format_chunk { my $self = shift; return $_[0] unless defined($_[0]) && length($_[0]); return _bytes(sprintf("%x", length($_[0])) . $CRLF . $_[0] . $CRLF); } sub write_chunk { my $self = shift; return 1 unless defined($_[0]) && length($_[0]); $self->print(_bytes(sprintf("%x", length($_[0])) . $CRLF . $_[0] . $CRLF)); } sub format_chunk_eof { my $self = shift; my @h; while (@_) { push(@h, sprintf "%s: %s$CRLF", splice(@_, 0, 2)); } return _bytes(join("", "0$CRLF", @h, $CRLF)); } sub write_chunk_eof { my $self = shift; $self->print($self->format_chunk_eof(@_)); } sub my_read { die if @_ > 3; my $self = shift; my $len = $_[1]; for (${*$self}{'http_buf'}) { if (length) { $_[0] = substr($_, 0, $len, ""); return length($_[0]); } else { die "read timeout" unless $self->can_read; return $self->sysread($_[0], $len); } } } sub my_readline { my $self = shift; my $what = shift; for (${*$self}{'http_buf'}) { my $max_line_length = ${*$self}{'http_max_line_length'}; my $pos; while (1) { # find line ending $pos = index($_, "\012"); last if $pos >= 0; die "$what line too long (limit is $max_line_length)" if $max_line_length && length($_) > $max_line_length; # need to read more data to find a line ending my $new_bytes = 0; READ: { # wait until bytes start arriving $self->can_read or die "read timeout"; # consume all incoming bytes my $bytes_read = $self->sysread($_, 1024, length); if(defined $bytes_read) { $new_bytes += $bytes_read; } elsif($!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK}) { redo READ; } else { # if we have already accumulated some data let's at # least return that as a line length or die "$what read failed: $!"; } # no line-ending, no new bytes return length($_) ? substr($_, 0, length($_), "") : undef if $new_bytes==0; } } die "$what line too long ($pos; limit is $max_line_length)" if $max_line_length && $pos > $max_line_length; my $line = substr($_, 0, $pos+1, ""); $line =~ s/(\015?\012)\z// || die "Assert"; return wantarray ? ($line, $1) : $line; } } sub can_read { my $self = shift; return 1 unless defined(fileno($self)); return 1 if $self->isa('IO::Socket::SSL') && $self->pending; return 1 if $self->isa('Net::SSL') && $self->can('pending') && $self->pending; # With no timeout, wait forever. An explicit timeout of 0 can be # used to just check if the socket is readable without waiting. my $timeout = @_ ? shift : (${*$self}{io_socket_timeout} || undef); my $fbits = ''; vec($fbits, fileno($self), 1) = 1; SELECT: { my $before; $before = time if $timeout; my $nfound = select($fbits, undef, undef, $timeout); if ($nfound < 0) { if ($!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK}) { # don't really think EAGAIN/EWOULDBLOCK can happen here if ($timeout) { $timeout -= time - $before; $timeout = 0 if $timeout < 0; } redo SELECT; } die "select failed: $!"; } return $nfound > 0; } } sub _rbuf { my $self = shift; if (@_) { for (${*$self}{'http_buf'}) { my $old; $old = $_ if defined wantarray; $_ = shift; return $old; } } else { return ${*$self}{'http_buf'}; } } sub _rbuf_length { my $self = shift; return length ${*$self}{'http_buf'}; } sub _read_header_lines { my $self = shift; my $junk_out = shift; my @headers; my $line_count = 0; my $max_header_lines = ${*$self}{'http_max_header_lines'}; while (my $line = my_readline($self, 'Header')) { if ($line =~ /^(\S+?)\s*:\s*(.*)/s) { push(@headers, $1, $2); } elsif (@headers && $line =~ s/^\s+//) { $headers[-1] .= " " . $line; } elsif ($junk_out) { push(@$junk_out, $line); } else { die "Bad header: '$line'\n"; } if ($max_header_lines) { $line_count++; if ($line_count >= $max_header_lines) { die "Too many header lines (limit is $max_header_lines)"; } } } return @headers; } sub read_response_headers { my($self, %opt) = @_; my $laxed = $opt{laxed}; my($status, $eol) = my_readline($self, 'Status'); unless (defined $status) { die "Server closed connection without sending any data back"; } my($peer_ver, $code, $message) = split(/\s+/, $status, 3); if (!$peer_ver || $peer_ver !~ s,^HTTP/,, || $code !~ /^[1-5]\d\d$/) { die "Bad response status line: '$status'" unless $laxed; # assume HTTP/0.9 ${*$self}{'http_peer_http_version'} = "0.9"; ${*$self}{'http_status'} = "200"; substr(${*$self}{'http_buf'}, 0, 0) = $status . ($eol || ""); return 200 unless wantarray; return (200, "Assumed OK"); }; ${*$self}{'http_peer_http_version'} = $peer_ver; ${*$self}{'http_status'} = $code; my $junk_out; if ($laxed) { $junk_out = $opt{junk_out} || []; } my @headers = $self->_read_header_lines($junk_out); # pick out headers that read_entity_body might need my @te; my $content_length; for (my $i = 0; $i < @headers; $i += 2) { my $h = lc($headers[$i]); if ($h eq 'transfer-encoding') { my $te = $headers[$i+1]; $te =~ s/^\s+//; $te =~ s/\s+$//; push(@te, $te) if length($te); } elsif ($h eq 'content-length') { # ignore bogus and overflow values if ($headers[$i+1] =~ /^\s*(\d{1,15})(?:\s|$)/) { $content_length = $1; } } } ${*$self}{'http_te'} = join(",", @te); ${*$self}{'http_content_length'} = $content_length; ${*$self}{'http_first_body'}++; delete ${*$self}{'http_trailers'}; return $code unless wantarray; return ($code, $message, @headers); } sub read_entity_body { my $self = shift; my $buf_ref = \$_[0]; my $size = $_[1]; die "Offset not supported yet" if $_[2]; my $chunked; my $bytes; if (${*$self}{'http_first_body'}) { ${*$self}{'http_first_body'} = 0; delete ${*$self}{'http_chunked'}; delete ${*$self}{'http_bytes'}; my $method = shift(@{${*$self}{'http_request_method'}}); my $status = ${*$self}{'http_status'}; if ($method eq "HEAD") { # this response is always empty regardless of other headers $bytes = 0; } elsif (my $te = ${*$self}{'http_te'}) { my @te = split(/\s*,\s*/, lc($te)); die "Chunked must be last Transfer-Encoding '$te'" unless pop(@te) eq "chunked"; pop(@te) while @te && $te[-1] eq "chunked"; # ignore repeated chunked spec for (@te) { if ($_ eq "deflate" && inflate_ok()) { #require Compress::Raw::Zlib; my ($i, $status) = Compress::Raw::Zlib::Inflate->new(); die "Can't make inflator: $status" unless $i; $_ = sub { my $out; $i->inflate($_[0], \$out); $out } } elsif ($_ eq "gzip" && gunzip_ok()) { #require IO::Uncompress::Gunzip; my @buf; $_ = sub { push(@buf, $_[0]); return "" unless $_[1]; my $input = join("", @buf); my $output; IO::Uncompress::Gunzip::gunzip(\$input, \$output, Transparent => 0) or die "Can't gunzip content: $IO::Uncompress::Gunzip::GunzipError"; return \$output; }; } elsif ($_ eq "identity") { $_ = sub { $_[0] }; } else { die "Can't handle transfer encoding '$te'"; } } @te = reverse(@te); ${*$self}{'http_te2'} = @te ? \@te : ""; $chunked = -1; } elsif (defined(my $content_length = ${*$self}{'http_content_length'})) { $bytes = $content_length; } elsif ($status =~ /^(?:1|[23]04)/) { # RFC 2616 says that these responses should always be empty # but that does not appear to be true in practice [RT#17907] $bytes = 0; } else { # XXX Multi-Part types are self delimiting, but RFC 2616 says we # only has to deal with 'multipart/byteranges' # Read until EOF } } else { $chunked = ${*$self}{'http_chunked'}; $bytes = ${*$self}{'http_bytes'}; } if (defined $chunked) { # The state encoded in $chunked is: # $chunked == 0: read CRLF after chunk, then chunk header # $chunked == -1: read chunk header # $chunked > 0: bytes left in current chunk to read if ($chunked <= 0) { my $line = my_readline($self, 'Entity body'); if ($chunked == 0) { die "Missing newline after chunk data: '$line'" if !defined($line) || $line ne ""; $line = my_readline($self, 'Entity body'); } die "EOF when chunk header expected" unless defined($line); my $chunk_len = $line; $chunk_len =~ s/;.*//; # ignore potential chunk parameters unless ($chunk_len =~ /^([\da-fA-F]+)\s*$/) { die "Bad chunk-size in HTTP response: $line"; } $chunked = hex($1); ${*$self}{'http_chunked'} = $chunked; if ($chunked == 0) { ${*$self}{'http_trailers'} = [$self->_read_header_lines]; $$buf_ref = ""; my $n = 0; if (my $transforms = delete ${*$self}{'http_te2'}) { for (@$transforms) { $$buf_ref = &$_($$buf_ref, 1); } $n = length($$buf_ref); } # in case somebody tries to read more, make sure we continue # to return EOF delete ${*$self}{'http_chunked'}; ${*$self}{'http_bytes'} = 0; return $n; } } my $n = $chunked; $n = $size if $size && $size < $n; $n = my_read($self, $$buf_ref, $n); return undef unless defined $n; ${*$self}{'http_chunked'} = $chunked - $n; if ($n > 0) { if (my $transforms = ${*$self}{'http_te2'}) { for (@$transforms) { $$buf_ref = &$_($$buf_ref, 0); } $n = length($$buf_ref); $n = -1 if $n == 0; } } return $n; } elsif (defined $bytes) { unless ($bytes) { $$buf_ref = ""; return 0; } my $n = $bytes; $n = $size if $size && $size < $n; $n = my_read($self, $$buf_ref, $n); ${*$self}{'http_bytes'} = defined $n ? $bytes - $n : $bytes; return $n; } else { # read until eof $size ||= 8*1024; return my_read($self, $$buf_ref, $size); } } sub get_trailers { my $self = shift; @{${*$self}{'http_trailers'} || []}; } BEGIN { my $gunzip_ok; my $inflate_ok; sub gunzip_ok { return $gunzip_ok if defined $gunzip_ok; # Try to load IO::Uncompress::Gunzip. local $@; local $SIG{__DIE__}; $gunzip_ok = 0; eval { require IO::Uncompress::Gunzip; $gunzip_ok++; }; return $gunzip_ok; } sub inflate_ok { return $inflate_ok if defined $inflate_ok; # Try to load Compress::Raw::Zlib. local $@; local $SIG{__DIE__}; $inflate_ok = 0; eval { require Compress::Raw::Zlib; $inflate_ok++; }; return $inflate_ok; } } # BEGIN 1; =pod =encoding UTF-8 =head1 NAME Net::HTTP::Methods - Methods shared by Net::HTTP and Net::HTTPS =head1 VERSION version 6.17 =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001-2017 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # ABSTRACT: Methods shared by Net::HTTP and Net::HTTPS PK f1]|dz+ + Domain.pmnu[# Net::Domain.pm # # Copyright (C) 1995-1998 Graham Barr. All rights reserved. # Copyright (C) 2013-2014 Steve Hay. All rights reserved. # This module is free software; you can redistribute it and/or modify it under # the same terms as Perl itself, i.e. under the terms of either the GNU General # Public License or the Artistic License, as specified in the F file. package Net::Domain; use 5.008001; use strict; use warnings; use Carp; use Exporter; use Net::Config; our @ISA = qw(Exporter); our @EXPORT_OK = qw(hostname hostdomain hostfqdn domainname); our $VERSION = "3.11"; my ($host, $domain, $fqdn) = (undef, undef, undef); # Try every conceivable way to get hostname. sub _hostname { # we already know it return $host if (defined $host); if ($^O eq 'MSWin32') { require Socket; my ($name, $alias, $type, $len, @addr) = gethostbyname($ENV{'COMPUTERNAME'} || 'localhost'); while (@addr) { my $a = shift(@addr); $host = gethostbyaddr($a, Socket::AF_INET()); last if defined $host; } if (defined($host) && index($host, '.') > 0) { $fqdn = $host; ($host, $domain) = $fqdn =~ /^([^.]+)\.(.*)$/; } return $host; } elsif ($^O eq 'MacOS') { chomp($host = `hostname`); } elsif ($^O eq 'VMS') { ## multiple varieties of net s/w makes this hard $host = $ENV{'UCX$INET_HOST'} if defined($ENV{'UCX$INET_HOST'}); $host = $ENV{'MULTINET_HOST_NAME'} if defined($ENV{'MULTINET_HOST_NAME'}); if (index($host, '.') > 0) { $fqdn = $host; ($host, $domain) = $fqdn =~ /^([^.]+)\.(.*)$/; } return $host; } else { local $SIG{'__DIE__'}; # syscall is preferred since it avoids tainting problems eval { my $tmp = "\0" x 256; ## preload scalar eval { package main; require "syscall.ph"; ## no critic (Modules::RequireBarewordIncludes) defined(&main::SYS_gethostname); } || eval { package main; require "sys/syscall.ph"; ## no critic (Modules::RequireBarewordIncludes) defined(&main::SYS_gethostname); } and $host = (syscall(&main::SYS_gethostname, $tmp, 256) == 0) ? $tmp : undef; } # POSIX || eval { require POSIX; $host = (POSIX::uname())[1]; } # trusty old hostname command || eval { chop($host = `(hostname) 2>/dev/null`); # BSD'ish } # sysV/POSIX uname command (may truncate) || eval { chop($host = `uname -n 2>/dev/null`); ## SYSV'ish && POSIX'ish } # Apollo pre-SR10 || eval { $host = (split(/[:. ]/, `/com/host`, 6))[0]; } || eval { $host = ""; }; } # remove garbage $host =~ s/[\0\r\n]+//go; $host =~ s/(\A\.+|\.+\Z)//go; $host =~ s/\.\.+/\./go; $host; } sub _hostdomain { # we already know it return $domain if (defined $domain); local $SIG{'__DIE__'}; return $domain = $NetConfig{'inet_domain'} if defined $NetConfig{'inet_domain'}; # try looking in /etc/resolv.conf # putting this here and assuming that it is correct, eliminates # calls to gethostbyname, and therefore DNS lookups. This helps # those on dialup systems. local ($_); if (open(my $res, '<', "/etc/resolv.conf")) { while (<$res>) { $domain = $1 if (/\A\s*(?:domain|search)\s+(\S+)/); } close($res); return $domain if (defined $domain); } # just try hostname and system calls my $host = _hostname(); my (@hosts); @hosts = ($host, "localhost"); unless (defined($host) && $host =~ /\./) { my $dom = undef; eval { my $tmp = "\0" x 256; ## preload scalar eval { package main; require "syscall.ph"; ## no critic (Modules::RequireBarewordIncludes) } || eval { package main; require "sys/syscall.ph"; ## no critic (Modules::RequireBarewordIncludes) } and $dom = (syscall(&main::SYS_getdomainname, $tmp, 256) == 0) ? $tmp : undef; }; if ($^O eq 'VMS') { $dom ||= $ENV{'TCPIP$INET_DOMAIN'} || $ENV{'UCX$INET_DOMAIN'}; } chop($dom = `domainname 2>/dev/null`) unless (defined $dom || $^O =~ /^(?:cygwin|MSWin32|android)/); if (defined $dom) { my @h = (); $dom =~ s/^\.+//; while (length($dom)) { push(@h, "$host.$dom"); $dom =~ s/^[^.]+.+// or last; } unshift(@hosts, @h); } } # Attempt to locate FQDN foreach (grep { defined $_ } @hosts) { my @info = gethostbyname($_); next unless @info; # look at real name & aliases foreach my $site ($info[0], split(/ /, $info[1])) { if (rindex($site, ".") > 0) { # Extract domain from FQDN ($domain = $site) =~ s/\A[^.]+\.//; return $domain; } } } # Look for environment variable $domain ||= $ENV{LOCALDOMAIN} || $ENV{DOMAIN}; if (defined $domain) { $domain =~ s/[\r\n\0]+//g; $domain =~ s/(\A\.+|\.+\Z)//g; $domain =~ s/\.\.+/\./g; } $domain; } sub domainname { return $fqdn if (defined $fqdn); _hostname(); # *.local names are special on darwin. If we call gethostbyname below, it # may hang while waiting for another, non-existent computer to respond. if($^O eq 'darwin' && $host =~ /\.local$/) { return $host; } _hostdomain(); # Assumption: If the host name does not contain a period # and the domain name does, then assume that they are correct # this helps to eliminate calls to gethostbyname, and therefore # eliminate DNS lookups return $fqdn = $host . "." . $domain if (defined $host and defined $domain and $host !~ /\./ and $domain =~ /\./); # For hosts that have no name, just an IP address return $fqdn = $host if defined $host and $host =~ /^\d+(\.\d+){3}$/; my @host = defined $host ? split(/\./, $host) : ('localhost'); my @domain = defined $domain ? split(/\./, $domain) : (); my @fqdn = (); # Determine from @host & @domain the FQDN my @d = @domain; LOOP: while (1) { my @h = @host; while (@h) { my $tmp = join(".", @h, @d); if ((gethostbyname($tmp))[0]) { @fqdn = (@h, @d); $fqdn = $tmp; last LOOP; } pop @h; } last unless shift @d; } if (@fqdn) { $host = shift @fqdn; until ((gethostbyname($host))[0]) { $host .= "." . shift @fqdn; } $domain = join(".", @fqdn); } else { undef $host; undef $domain; undef $fqdn; } $fqdn; } sub hostfqdn { domainname() } sub hostname { domainname() unless (defined $host); return $host; } sub hostdomain { domainname() unless (defined $domain); return $domain; } 1; # Keep require happy __END__ =head1 NAME Net::Domain - Attempt to evaluate the current host's internet name and domain =head1 SYNOPSIS use Net::Domain qw(hostname hostfqdn hostdomain domainname); =head1 DESCRIPTION Using various methods B to find the Fully Qualified Domain Name (FQDN) of the current host. From this determine the host-name and the host-domain. Each of the functions will return I if the FQDN cannot be determined. =over 4 =item hostfqdn () Identify and return the FQDN of the current host. =item domainname () An alias for hostfqdn (). =item hostname () Returns the smallest part of the FQDN which can be used to identify the host. =item hostdomain () Returns the remainder of the FQDN after the I has been removed. =back =head1 AUTHOR Graham Barr EFE. Adapted from Sys::Hostname by David Sundstrom EFE. Steve Hay EFE is now maintaining libnet as of version 1.22_02. =head1 COPYRIGHT Copyright (C) 1995-1998 Graham Barr. All rights reserved. Copyright (C) 2013-2014 Steve Hay. All rights reserved. =head1 LICENCE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e. under the terms of either the GNU General Public License or the Artistic License, as specified in the F file. =cut PK f1]7XkuPuPCmd.pmnu[# Net::Cmd.pm # # Copyright (C) 1995-2006 Graham Barr. All rights reserved. # Copyright (C) 2013-2016 Steve Hay. All rights reserved. # This module is free software; you can redistribute it and/or modify it under # the same terms as Perl itself, i.e. under the terms of either the GNU General # Public License or the Artistic License, as specified in the F file. package Net::Cmd; use 5.008001; use strict; use warnings; use Carp; use Exporter; use Symbol 'gensym'; use Errno 'EINTR'; BEGIN { if ($^O eq 'os390') { require Convert::EBCDIC; # Convert::EBCDIC->import; } } our $VERSION = "3.11"; our @ISA = qw(Exporter); our @EXPORT = qw(CMD_INFO CMD_OK CMD_MORE CMD_REJECT CMD_ERROR CMD_PENDING); use constant CMD_INFO => 1; use constant CMD_OK => 2; use constant CMD_MORE => 3; use constant CMD_REJECT => 4; use constant CMD_ERROR => 5; use constant CMD_PENDING => 0; use constant DEF_REPLY_CODE => 421; my %debug = (); my $tr = $^O eq 'os390' ? Convert::EBCDIC->new() : undef; sub toebcdic { my $cmd = shift; unless (exists ${*$cmd}{'net_cmd_asciipeer'}) { my $string = $_[0]; my $ebcdicstr = $tr->toebcdic($string); ${*$cmd}{'net_cmd_asciipeer'} = $string !~ /^\d+/ && $ebcdicstr =~ /^\d+/; } ${*$cmd}{'net_cmd_asciipeer'} ? $tr->toebcdic($_[0]) : $_[0]; } sub toascii { my $cmd = shift; ${*$cmd}{'net_cmd_asciipeer'} ? $tr->toascii($_[0]) : $_[0]; } sub _print_isa { no strict 'refs'; ## no critic (TestingAndDebugging::ProhibitNoStrict) my $pkg = shift; my $cmd = $pkg; $debug{$pkg} ||= 0; my %done = (); my @do = ($pkg); my %spc = ($pkg, ""); while ($pkg = shift @do) { next if defined $done{$pkg}; $done{$pkg} = 1; my $v = defined ${"${pkg}::VERSION"} ? "(" . ${"${pkg}::VERSION"} . ")" : ""; my $spc = $spc{$pkg}; $cmd->debug_print(1, "${spc}${pkg}${v}\n"); if (@{"${pkg}::ISA"}) { @spc{@{"${pkg}::ISA"}} = (" " . $spc{$pkg}) x @{"${pkg}::ISA"}; unshift(@do, @{"${pkg}::ISA"}); } } } sub debug { @_ == 1 or @_ == 2 or croak 'usage: $obj->debug([LEVEL])'; my ($cmd, $level) = @_; my $pkg = ref($cmd) || $cmd; my $oldval = 0; if (ref($cmd)) { $oldval = ${*$cmd}{'net_cmd_debug'} || 0; } else { $oldval = $debug{$pkg} || 0; } return $oldval unless @_ == 2; $level = $debug{$pkg} || 0 unless defined $level; _print_isa($pkg) if ($level && !exists $debug{$pkg}); if (ref($cmd)) { ${*$cmd}{'net_cmd_debug'} = $level; } else { $debug{$pkg} = $level; } $oldval; } sub message { @_ == 1 or croak 'usage: $obj->message()'; my $cmd = shift; wantarray ? @{${*$cmd}{'net_cmd_resp'}} : join("", @{${*$cmd}{'net_cmd_resp'}}); } sub debug_text { $_[2] } sub debug_print { my ($cmd, $out, $text) = @_; print STDERR $cmd, ($out ? '>>> ' : '<<< '), $cmd->debug_text($out, $text); } sub code { @_ == 1 or croak 'usage: $obj->code()'; my $cmd = shift; ${*$cmd}{'net_cmd_code'} = $cmd->DEF_REPLY_CODE unless exists ${*$cmd}{'net_cmd_code'}; ${*$cmd}{'net_cmd_code'}; } sub status { @_ == 1 or croak 'usage: $obj->status()'; my $cmd = shift; substr(${*$cmd}{'net_cmd_code'}, 0, 1); } sub set_status { @_ == 3 or croak 'usage: $obj->set_status(CODE, MESSAGE)'; my $cmd = shift; my ($code, $resp) = @_; $resp = defined $resp ? [$resp] : [] unless ref($resp); (${*$cmd}{'net_cmd_code'}, ${*$cmd}{'net_cmd_resp'}) = ($code, $resp); 1; } sub _syswrite_with_timeout { my $cmd = shift; my $line = shift; my $len = length($line); my $offset = 0; my $win = ""; vec($win, fileno($cmd), 1) = 1; my $timeout = $cmd->timeout || undef; my $initial = time; my $pending = $timeout; local $SIG{PIPE} = 'IGNORE' unless $^O eq 'MacOS'; while ($len) { my $wout; my $nfound = select(undef, $wout = $win, undef, $pending); if ((defined $nfound and $nfound > 0) or -f $cmd) # -f for testing on win32 { my $w = syswrite($cmd, $line, $len, $offset); if (! defined($w) ) { my $err = $!; $cmd->close; $cmd->_set_status_closed($err); return; } $len -= $w; $offset += $w; } elsif ($nfound == -1) { if ( $! == EINTR ) { if ( defined($timeout) ) { redo if ($pending = $timeout - ( time - $initial ) ) > 0; $cmd->_set_status_timeout; return; } redo; } my $err = $!; $cmd->close; $cmd->_set_status_closed($err); return; } else { $cmd->_set_status_timeout; return; } } return 1; } sub _set_status_timeout { my $cmd = shift; my $pkg = ref($cmd) || $cmd; $cmd->set_status($cmd->DEF_REPLY_CODE, "[$pkg] Timeout"); carp(ref($cmd) . ": " . (caller(1))[3] . "(): timeout") if $cmd->debug; } sub _set_status_closed { my $cmd = shift; my $err = shift; my $pkg = ref($cmd) || $cmd; $cmd->set_status($cmd->DEF_REPLY_CODE, "[$pkg] Connection closed"); carp(ref($cmd) . ": " . (caller(1))[3] . "(): unexpected EOF on command channel: $err") if $cmd->debug; } sub _is_closed { my $cmd = shift; if (!defined fileno($cmd)) { $cmd->_set_status_closed($!); return 1; } return 0; } sub command { my $cmd = shift; return $cmd if $cmd->_is_closed; $cmd->dataend() if (exists ${*$cmd}{'net_cmd_last_ch'}); if (scalar(@_)) { my $str = join( " ", map { /\n/ ? do { my $n = $_; $n =~ tr/\n/ /; $n } : $_; } @_ ); $str = $cmd->toascii($str) if $tr; $str .= "\015\012"; $cmd->debug_print(1, $str) if ($cmd->debug); # though documented to return undef on failure, the legacy behavior # was to return $cmd even on failure, so this odd construct does that $cmd->_syswrite_with_timeout($str) or return $cmd; } $cmd; } sub ok { @_ == 1 or croak 'usage: $obj->ok()'; my $code = $_[0]->code; 0 < $code && $code < 400; } sub unsupported { my $cmd = shift; $cmd->set_status(580, 'Unsupported command'); 0; } sub getline { my $cmd = shift; ${*$cmd}{'net_cmd_lines'} ||= []; return shift @{${*$cmd}{'net_cmd_lines'}} if scalar(@{${*$cmd}{'net_cmd_lines'}}); my $partial = defined(${*$cmd}{'net_cmd_partial'}) ? ${*$cmd}{'net_cmd_partial'} : ""; return if $cmd->_is_closed; my $fd = fileno($cmd); my $rin = ""; vec($rin, $fd, 1) = 1; my $buf; until (scalar(@{${*$cmd}{'net_cmd_lines'}})) { my $timeout = $cmd->timeout || undef; my $rout; my $select_ret = select($rout = $rin, undef, undef, $timeout); if ($select_ret > 0) { unless (sysread($cmd, $buf = "", 1024)) { my $err = $!; $cmd->close; $cmd->_set_status_closed($err); return; } substr($buf, 0, 0) = $partial; ## prepend from last sysread my @buf = split(/\015?\012/, $buf, -1); ## break into lines $partial = pop @buf; push(@{${*$cmd}{'net_cmd_lines'}}, map {"$_\n"} @buf); } else { $cmd->_set_status_timeout; return; } } ${*$cmd}{'net_cmd_partial'} = $partial; if ($tr) { foreach my $ln (@{${*$cmd}{'net_cmd_lines'}}) { $ln = $cmd->toebcdic($ln); } } shift @{${*$cmd}{'net_cmd_lines'}}; } sub ungetline { my ($cmd, $str) = @_; ${*$cmd}{'net_cmd_lines'} ||= []; unshift(@{${*$cmd}{'net_cmd_lines'}}, $str); } sub parse_response { return () unless $_[1] =~ s/^(\d\d\d)(.?)//o; ($1, $2 eq "-"); } sub response { my $cmd = shift; my ($code, $more) = (undef) x 2; $cmd->set_status($cmd->DEF_REPLY_CODE, undef); # initialize the response while (1) { my $str = $cmd->getline(); return CMD_ERROR unless defined($str); $cmd->debug_print(0, $str) if ($cmd->debug); ($code, $more) = $cmd->parse_response($str); unless (defined $code) { carp("$cmd: response(): parse error in '$str'") if ($cmd->debug); $cmd->ungetline($str); $@ = $str; # $@ used as tunneling hack return CMD_ERROR; } ${*$cmd}{'net_cmd_code'} = $code; push(@{${*$cmd}{'net_cmd_resp'}}, $str); last unless ($more); } return unless defined $code; substr($code, 0, 1); } sub read_until_dot { my $cmd = shift; my $fh = shift; my $arr = []; while (1) { my $str = $cmd->getline() or return; $cmd->debug_print(0, $str) if ($cmd->debug & 4); last if ($str =~ /^\.\r?\n/o); $str =~ s/^\.\././o; if (defined $fh) { print $fh $str; } else { push(@$arr, $str); } } $arr; } sub datasend { my $cmd = shift; my $arr = @_ == 1 && ref($_[0]) ? $_[0] : \@_; my $line = join("", @$arr); # Perls < 5.10.1 (with the exception of 5.8.9) have a performance problem with # the substitutions below when dealing with strings stored internally in # UTF-8, so downgrade them (if possible). # Data passed to datasend() should be encoded to octets upstream already so # shouldn't even have the UTF-8 flag on to start with, but if it so happens # that the octets are stored in an upgraded string (as can sometimes occur) # then they would still downgrade without fail anyway. # Only Unicode codepoints > 0xFF stored in an upgraded string will fail to # downgrade. We fail silently in that case, and a "Wide character in print" # warning will be emitted later by syswrite(). utf8::downgrade($line, 1) if $] < 5.010001 && $] != 5.008009; return 0 if $cmd->_is_closed; my $last_ch = ${*$cmd}{'net_cmd_last_ch'}; # We have not send anything yet, so last_ch = "\012" means we are at the start of a line $last_ch = ${*$cmd}{'net_cmd_last_ch'} = "\012" unless defined $last_ch; return 1 unless length $line; if ($cmd->debug) { foreach my $b (split(/\n/, $line)) { $cmd->debug_print(1, "$b\n"); } } $line =~ tr/\r\n/\015\012/ unless "\r" eq "\015"; my $first_ch = ''; if ($last_ch eq "\015") { # Remove \012 so it does not get prefixed with another \015 below # and escape the . if there is one following it because the fixup # below will not find it $first_ch = "\012" if $line =~ s/^\012(\.?)/$1$1/; } elsif ($last_ch eq "\012") { # Fixup below will not find the . as the first character of the buffer $first_ch = "." if $line =~ /^\./; } $line =~ s/\015?\012(\.?)/\015\012$1$1/sg; substr($line, 0, 0) = $first_ch; ${*$cmd}{'net_cmd_last_ch'} = substr($line, -1, 1); $cmd->_syswrite_with_timeout($line) or return; 1; } sub rawdatasend { my $cmd = shift; my $arr = @_ == 1 && ref($_[0]) ? $_[0] : \@_; my $line = join("", @$arr); return 0 if $cmd->_is_closed; return 1 unless length($line); if ($cmd->debug) { my $b = "$cmd>>> "; print STDERR $b, join("\n$b", split(/\n/, $line)), "\n"; } $cmd->_syswrite_with_timeout($line) or return; 1; } sub dataend { my $cmd = shift; return 0 if $cmd->_is_closed; my $ch = ${*$cmd}{'net_cmd_last_ch'}; my $tosend; if (!defined $ch) { return 1; } elsif ($ch ne "\012") { $tosend = "\015\012"; } $tosend .= ".\015\012"; $cmd->debug_print(1, ".\n") if ($cmd->debug); $cmd->_syswrite_with_timeout($tosend) or return 0; delete ${*$cmd}{'net_cmd_last_ch'}; $cmd->response() == CMD_OK; } # read and write to tied filehandle sub tied_fh { my $cmd = shift; ${*$cmd}{'net_cmd_readbuf'} = ''; my $fh = gensym(); tie *$fh, ref($cmd), $cmd; return $fh; } # tie to myself sub TIEHANDLE { my $class = shift; my $cmd = shift; return $cmd; } # Tied filehandle read. Reads requested data length, returning # end-of-file when the dot is encountered. sub READ { my $cmd = shift; my ($len, $offset) = @_[1, 2]; return unless exists ${*$cmd}{'net_cmd_readbuf'}; my $done = 0; while (!$done and length(${*$cmd}{'net_cmd_readbuf'}) < $len) { ${*$cmd}{'net_cmd_readbuf'} .= $cmd->getline() or return; $done++ if ${*$cmd}{'net_cmd_readbuf'} =~ s/^\.\r?\n\Z//m; } $_[0] = ''; substr($_[0], $offset + 0) = substr(${*$cmd}{'net_cmd_readbuf'}, 0, $len); substr(${*$cmd}{'net_cmd_readbuf'}, 0, $len) = ''; delete ${*$cmd}{'net_cmd_readbuf'} if $done; return length $_[0]; } sub READLINE { my $cmd = shift; # in this context, we use the presence of readbuf to # indicate that we have not yet reached the eof return unless exists ${*$cmd}{'net_cmd_readbuf'}; my $line = $cmd->getline; return if $line =~ /^\.\r?\n/; $line; } sub PRINT { my $cmd = shift; my ($buf, $len, $offset) = @_; $len ||= length($buf); $offset += 0; return unless $cmd->datasend(substr($buf, $offset, $len)); ${*$cmd}{'net_cmd_sending'}++; # flag that we should call dataend() return $len; } sub CLOSE { my $cmd = shift; my $r = exists(${*$cmd}{'net_cmd_sending'}) ? $cmd->dataend : 1; delete ${*$cmd}{'net_cmd_readbuf'}; delete ${*$cmd}{'net_cmd_sending'}; $r; } 1; __END__ =head1 NAME Net::Cmd - Network Command class (as used by FTP, SMTP etc) =head1 SYNOPSIS use Net::Cmd; @ISA = qw(Net::Cmd); =head1 DESCRIPTION C is a collection of methods that can be inherited by a sub-class of C. These methods implement the functionality required for a command based protocol, for example FTP and SMTP. If your sub-class does not also derive from C or similar (e.g. C, C or C) then you must provide the following methods by other means yourself: C and C. =head1 USER METHODS These methods provide a user interface to the C object. =over 4 =item debug ( VALUE ) Set the level of debug information for this object. If C is not given then the current state is returned. Otherwise the state is changed to C and the previous state returned. Different packages may implement different levels of debug but a non-zero value results in copies of all commands and responses also being sent to STDERR. If C is C then the debug level will be set to the default debug level for the class. This method can also be called as a I method to set/get the default debug level for a given class. =item message () Returns the text message returned from the last command. In a scalar context it returns a single string, in a list context it will return each line as a separate element. (See L below.) =item code () Returns the 3-digit code from the last command. If a command is pending then the value 0 is returned. (See L below.) =item ok () Returns non-zero if the last code value was greater than zero and less than 400. This holds true for most command servers. Servers where this does not hold may override this method. =item status () Returns the most significant digit of the current status code. If a command is pending then C is returned. =item datasend ( DATA ) Send data to the remote server, converting LF to CRLF. Any line starting with a '.' will be prefixed with another '.'. C may be an array or a reference to an array. The C passed in must be encoded by the caller to octets of whatever encoding is required, e.g. by using the Encode module's C function. =item dataend () End the sending of data to the remote server. This is done by ensuring that the data already sent ends with CRLF then sending '.CRLF' to end the transmission. Once this data has been sent C calls C and returns true if C returns CMD_OK. =back =head1 CLASS METHODS These methods are not intended to be called by the user, but used or over-ridden by a sub-class of C =over 4 =item debug_print ( DIR, TEXT ) Print debugging information. C denotes the direction I being data being sent to the server. Calls C before printing to STDERR. =item debug_text ( DIR, TEXT ) This method is called to print debugging information. TEXT is the text being sent. The method should return the text to be printed. This is primarily meant for the use of modules such as FTP where passwords are sent, but we do not want to display them in the debugging information. =item command ( CMD [, ARGS, ... ]) Send a command to the command server. All arguments are first joined with a space character and CRLF is appended, this string is then sent to the command server. Returns undef upon failure. =item unsupported () Sets the status code to 580 and the response text to 'Unsupported command'. Returns zero. =item response () Obtain a response from the server. Upon success the most significant digit of the status code is returned. Upon failure, timeout etc., I is returned. =item parse_response ( TEXT ) This method is called by C as a method with one argument. It should return an array of 2 values, the 3-digit status code and a flag which is true when this is part of a multi-line response and this line is not the last. =item getline () Retrieve one line, delimited by CRLF, from the remote server. Returns I upon failure. B: If you do use this method for any reason, please remember to add some C calls into your method. =item ungetline ( TEXT ) Unget a line of text from the server. =item rawdatasend ( DATA ) Send data to the remote server without performing any conversions. C is a scalar. As with C, the C passed in must be encoded by the caller to octets of whatever encoding is required, e.g. by using the Encode module's C function. =item read_until_dot () Read data from the remote server until a line consisting of a single '.'. Any lines starting with '..' will have one of the '.'s removed. Returns a reference to a list containing the lines, or I upon failure. =item tied_fh () Returns a filehandle tied to the Net::Cmd object. After issuing a command, you may read from this filehandle using read() or <>. The filehandle will return EOF when the final dot is encountered. Similarly, you may write to the filehandle in order to send data to the server after issuing a command that expects data to be written. See the Net::POP3 and Net::SMTP modules for examples of this. =back =head1 PSEUDO RESPONSES Normally the values returned by C and C are obtained from the remote server, but in a few circumstances, as detailed below, C will return values that it sets. You can alter this behavior by overriding DEF_REPLY_CODE() to specify a different default reply code, or overriding one of the specific error handling methods below. =over 4 =item Initial value Before any command has executed or if an unexpected error occurs C will return "421" (temporary connection failure) and C will return undef. =item Connection closed If the underlying C is closed, or if there are any read or write failures, the file handle will be forced closed, and C will return "421" (temporary connection failure) and C will return "[$pkg] Connection closed" (where $pkg is the name of the class that subclassed C). The _set_status_closed() method can be overridden to set a different message (by calling set_status()) or otherwise trap this error. =item Timeout If there is a read or write timeout C will return "421" (temporary connection failure) and C will return "[$pkg] Timeout" (where $pkg is the name of the class that subclassed C). The _set_status_timeout() method can be overridden to set a different message (by calling set_status()) or otherwise trap this error. =back =head1 EXPORTS C exports six subroutines, five of these, C, C, C, C and C, correspond to possible results of C and C. The sixth is C. =head1 AUTHOR Graham Barr EFE. Steve Hay EFE is now maintaining libnet as of version 1.22_02. =head1 COPYRIGHT Copyright (C) 1995-2006 Graham Barr. All rights reserved. Copyright (C) 2013-2016 Steve Hay. All rights reserved. =head1 LICENCE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e. under the terms of either the GNU General Public License or the Artistic License, as specified in the F file. =cut PK f1]_(!(! Config.pmnu[# Net::Config.pm # # Copyright (C) 2000 Graham Barr. All rights reserved. # Copyright (C) 2013-2014, 2016 Steve Hay. All rights reserved. # This module is free software; you can redistribute it and/or modify it under # the same terms as Perl itself, i.e. under the terms of either the GNU General # Public License or the Artistic License, as specified in the F file. package Net::Config; use 5.008001; use strict; use warnings; use Exporter; use Socket qw(inet_aton inet_ntoa); our @EXPORT = qw(%NetConfig); our @ISA = qw(Net::LocalCfg Exporter); our $VERSION = "3.11"; our($CONFIGURE, $LIBNET_CFG); eval { local @INC = @INC; pop @INC if $INC[-1] eq '.'; local $SIG{__DIE__}; require Net::LocalCfg; }; our %NetConfig = ( nntp_hosts => [], snpp_hosts => [], pop3_hosts => [], smtp_hosts => [], ph_hosts => [], daytime_hosts => [], time_hosts => [], inet_domain => undef, ftp_firewall => undef, ftp_ext_passive => 1, ftp_int_passive => 1, test_hosts => 1, test_exist => 1, ); # # Try to get as much configuration info as possible from InternetConfig # { ## no critic (BuiltinFunctions::ProhibitStringyEval) $^O eq 'MacOS' and eval < [ \$InternetConfig{ kICNNTPHost() } ], pop3_hosts => [ \$InternetConfig{ kICMailAccount() } =~ /\@(.*)/ ], smtp_hosts => [ \$InternetConfig{ kICSMTPHost() } ], ftp_testhost => \$InternetConfig{ kICFTPHost() } ? \$InternetConfig{ kICFTPHost()} : undef, ph_hosts => [ \$InternetConfig{ kICPhHost() } ], ftp_ext_passive => \$InternetConfig{"646F676F\xA5UsePassiveMode"} || 0, ftp_int_passive => \$InternetConfig{"646F676F\xA5UsePassiveMode"} || 0, socks_hosts => \$InternetConfig{ kICUseSocks() } ? [ \$InternetConfig{ kICSocksHost() } ] : [], ftp_firewall => \$InternetConfig{ kICUseFTPProxy() } ? [ \$InternetConfig{ kICFTPProxyHost() } ] : [], ); \@NetConfig{keys %nc} = values %nc; } TRY_INTERNET_CONFIG } my $file = __FILE__; my $ref; $file =~ s/Config.pm/libnet.cfg/; if (-f $file) { $ref = eval { local $SIG{__DIE__}; do $file }; if (ref($ref) eq 'HASH') { %NetConfig = (%NetConfig, %{$ref}); $LIBNET_CFG = $file; } } if ($< == $> and !$CONFIGURE) { my $home = eval { local $SIG{__DIE__}; (getpwuid($>))[7] } || $ENV{HOME}; $home ||= $ENV{HOMEDRIVE} . ($ENV{HOMEPATH} || '') if defined $ENV{HOMEDRIVE}; if (defined $home) { $file = $home . "/.libnetrc"; $ref = eval { local $SIG{__DIE__}; do $file } if -f $file; %NetConfig = (%NetConfig, %{$ref}) if ref($ref) eq 'HASH'; } } my ($k, $v); while (($k, $v) = each %NetConfig) { $NetConfig{$k} = [$v] if ($k =~ /_hosts$/ and $k ne "test_hosts" and defined($v) and !ref($v)); } # Take a hostname and determine if it is inside the firewall sub requires_firewall { shift; # ignore package my $host = shift; return 0 unless defined $NetConfig{'ftp_firewall'}; $host = inet_aton($host) or return -1; $host = inet_ntoa($host); if (exists $NetConfig{'local_netmask'}) { my $quad = unpack("N", pack("C*", split(/\./, $host))); my $list = $NetConfig{'local_netmask'}; $list = [$list] unless ref($list); foreach (@$list) { my ($net, $bits) = (m#^(\d+\.\d+\.\d+\.\d+)/(\d+)$#) or next; my $mask = ~0 << (32 - $bits); my $addr = unpack("N", pack("C*", split(/\./, $net))); return 0 if (($addr & $mask) == ($quad & $mask)); } return 1; } return 0; } *is_external = \&requires_firewall; 1; __END__ =head1 NAME Net::Config - Local configuration data for libnet =head1 SYNOPSIS use Net::Config qw(%NetConfig); =head1 DESCRIPTION C holds configuration data for the modules in the libnet distribution. During installation you will be asked for these values. The configuration data is held globally in a file in the perl installation tree, but a user may override any of these values by providing their own. This can be done by having a C<.libnetrc> file in their home directory. This file should return a reference to a HASH containing the keys described below. For example # .libnetrc { nntp_hosts => [ "my_preferred_host" ], ph_hosts => [ "my_ph_server" ], } __END__ =head1 METHODS C defines the following methods. They are methods as they are invoked as class methods. This is because C inherits from C so you can override these methods if you want. =over 4 =item requires_firewall ( HOST ) Attempts to determine if a given host is outside your firewall. Possible return values are. -1 Cannot lookup hostname 0 Host is inside firewall (or there is no ftp_firewall entry) 1 Host is outside the firewall This is done by using hostname lookup and the C entry in the configuration data. =back =head1 NetConfig VALUES =over 4 =item nntp_hosts =item snpp_hosts =item pop3_hosts =item smtp_hosts =item ph_hosts =item daytime_hosts =item time_hosts Each is a reference to an array of hostnames (in order of preference), which should be used for the given protocol =item inet_domain Your internet domain name =item ftp_firewall If you have an FTP proxy firewall (B an HTTP or SOCKS firewall) then this value should be set to the firewall hostname. If your firewall does not listen to port 21, then this value should be set to C<"hostname:port"> (eg C<"hostname:99">) =item ftp_firewall_type There are many different ftp firewall products available. But unfortunately there is no standard for how to traverse a firewall. The list below shows the sequence of commands that Net::FTP will use user Username for remote host pass Password for remote host fwuser Username for firewall fwpass Password for firewall remote.host The hostname of the remote ftp server =over 4 =item 0Z<> There is no firewall =item 1Z<> USER user@remote.host PASS pass =item 2Z<> USER fwuser PASS fwpass USER user@remote.host PASS pass =item 3Z<> USER fwuser PASS fwpass SITE remote.site USER user PASS pass =item 4Z<> USER fwuser PASS fwpass OPEN remote.site USER user PASS pass =item 5Z<> USER user@fwuser@remote.site PASS pass@fwpass =item 6Z<> USER fwuser@remote.site PASS fwpass USER user PASS pass =item 7Z<> USER user@remote.host PASS pass AUTH fwuser RESP fwpass =back =item ftp_ext_passive =item ftp_int_passive FTP servers can work in passive or active mode. Active mode is when you want to transfer data you have to tell the server the address and port to connect to. Passive mode is when the server provide the address and port and you establish the connection. With some firewalls active mode does not work as the server cannot connect to your machine (because you are behind a firewall) and the firewall does not re-write the command. In this case you should set C to a I value. Some servers are configured to only work in passive mode. If you have one of these you can force C to always transfer in passive mode; when not going via a firewall, by setting C to a I value. =item local_netmask A reference to a list of netmask strings in the form C<"134.99.4.0/24">. These are used by the C function to determine if a given host is inside or outside your firewall. =back The following entries are used during installation & testing on the libnet package =over 4 =item test_hosts If true then C may attempt to connect to hosts given in the configuration. =item test_exists If true then C will check each hostname given that it exists =back =head1 AUTHOR Graham Barr EFE. Steve Hay EFE is now maintaining libnet as of version 1.22_02. =head1 COPYRIGHT Copyright (C) 1998-2011 Graham Barr. All rights reserved. Copyright (C) 2013-2014, 2016 Steve Hay. All rights reserved. =head1 LICENCE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e. under the terms of either the GNU General Public License or the Artistic License, as specified in the F file. =cut PK f1]ppNNTP.pmnu[# Net::NNTP.pm # # Copyright (C) 1995-1997 Graham Barr. All rights reserved. # Copyright (C) 2013-2016 Steve Hay. All rights reserved. # This module is free software; you can redistribute it and/or modify it under # the same terms as Perl itself, i.e. under the terms of either the GNU General # Public License or the Artistic License, as specified in the F file. package Net::NNTP; use 5.008001; use strict; use warnings; use Carp; use IO::Socket; use Net::Cmd; use Net::Config; use Time::Local; our $VERSION = "3.11"; # Code for detecting if we can use SSL my $ssl_class = eval { require IO::Socket::SSL; # first version with default CA on most platforms no warnings 'numeric'; IO::Socket::SSL->VERSION(2.007); } && 'IO::Socket::SSL'; my $nossl_warn = !$ssl_class && 'To use SSL please install IO::Socket::SSL with version>=2.007'; # Code for detecting if we can use IPv6 my $family_key = 'Domain'; my $inet6_class = eval { require IO::Socket::IP; no warnings 'numeric'; IO::Socket::IP->VERSION(0.25) || die; $family_key = 'Family'; } && 'IO::Socket::IP' || eval { require IO::Socket::INET6; no warnings 'numeric'; IO::Socket::INET6->VERSION(2.62); } && 'IO::Socket::INET6'; sub can_ssl { $ssl_class }; sub can_inet6 { $inet6_class }; our @ISA = ('Net::Cmd', $inet6_class || 'IO::Socket::INET'); sub new { my $self = shift; my $type = ref($self) || $self; my ($host, %arg); if (@_ % 2) { $host = shift; %arg = @_; } else { %arg = @_; $host = delete $arg{Host}; } my $obj; $host ||= $ENV{NNTPSERVER} || $ENV{NEWSHOST}; my $hosts = defined $host ? [$host] : $NetConfig{nntp_hosts}; @{$hosts} = qw(news) unless @{$hosts}; my %connect = ( Proto => 'tcp'); if ($arg{SSL}) { # SSL from start die $nossl_warn if ! $ssl_class; $arg{Port} ||= 563; $connect{$_} = $arg{$_} for(grep { m{^SSL_} } keys %arg); } foreach my $o (qw(LocalAddr LocalPort Timeout)) { $connect{$o} = $arg{$o} if exists $arg{$o}; } $connect{$family_key} = $arg{Domain} || $arg{Family}; $connect{Timeout} = 120 unless defined $connect{Timeout}; $connect{PeerPort} = $arg{Port} || 'nntp(119)'; foreach my $h (@{$hosts}) { $connect{PeerAddr} = $h; $obj = $type->SUPER::new(%connect) or next; ${*$obj}{'net_nntp_host'} = $h; ${*$obj}{'net_nntp_arg'} = \%arg; if ($arg{SSL}) { Net::NNTP::_SSL->start_SSL($obj,%arg) or next; } last: } return unless defined $obj; $obj->autoflush(1); $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef); unless ($obj->response() == CMD_OK) { $obj->close; return; } my $c = $obj->code; my @m = $obj->message; unless (exists $arg{Reader} && $arg{Reader} == 0) { # if server is INN and we have transfer rights the we are currently # talking to innd not nnrpd if ($obj->reader) { # If reader succeeds the we need to consider this code to determine postok $c = $obj->code; } else { # I want to ignore this failure, so restore the previous status. $obj->set_status($c, \@m); } } ${*$obj}{'net_nntp_post'} = $c == 200 ? 1 : 0; $obj; } sub host { my $me = shift; ${*$me}{'net_nntp_host'}; } sub debug_text { my $nntp = shift; my $inout = shift; my $text = shift; if ( (ref($nntp) and $nntp->code == 350 and $text =~ /^(\S+)/) || ($text =~ /^(authinfo\s+pass)/io)) { $text = "$1 ....\n"; } $text; } sub postok { @_ == 1 or croak 'usage: $nntp->postok()'; my $nntp = shift; ${*$nntp}{'net_nntp_post'} || 0; } sub starttls { my $self = shift; $ssl_class or die $nossl_warn; $self->_STARTTLS or return; Net::NNTP::_SSL->start_SSL($self, %{ ${*$self}{'net_nntp_arg'} }, # (ssl) args given in new @_ # more (ssl) args ) or return; return 1; } sub article { @_ >= 1 && @_ <= 3 or croak 'usage: $nntp->article( [ MSGID ], [ FH ] )'; my $nntp = shift; my @fh; @fh = (pop) if @_ == 2 || (@_ && (ref($_[0]) || ref(\$_[0]) eq 'GLOB')); $nntp->_ARTICLE(@_) ? $nntp->read_until_dot(@fh) : undef; } sub articlefh { @_ >= 1 && @_ <= 2 or croak 'usage: $nntp->articlefh( [ MSGID ] )'; my $nntp = shift; return unless $nntp->_ARTICLE(@_); return $nntp->tied_fh; } sub authinfo { @_ == 3 or croak 'usage: $nntp->authinfo( USER, PASS )'; my ($nntp, $user, $pass) = @_; $nntp->_AUTHINFO("USER", $user) == CMD_MORE && $nntp->_AUTHINFO("PASS", $pass) == CMD_OK; } sub authinfo_simple { @_ == 3 or croak 'usage: $nntp->authinfo( USER, PASS )'; my ($nntp, $user, $pass) = @_; $nntp->_AUTHINFO('SIMPLE') == CMD_MORE && $nntp->command($user, $pass)->response == CMD_OK; } sub body { @_ >= 1 && @_ <= 3 or croak 'usage: $nntp->body( [ MSGID ], [ FH ] )'; my $nntp = shift; my @fh; @fh = (pop) if @_ == 2 || (@_ && ref($_[0]) || ref(\$_[0]) eq 'GLOB'); $nntp->_BODY(@_) ? $nntp->read_until_dot(@fh) : undef; } sub bodyfh { @_ >= 1 && @_ <= 2 or croak 'usage: $nntp->bodyfh( [ MSGID ] )'; my $nntp = shift; return unless $nntp->_BODY(@_); return $nntp->tied_fh; } sub head { @_ >= 1 && @_ <= 3 or croak 'usage: $nntp->head( [ MSGID ], [ FH ] )'; my $nntp = shift; my @fh; @fh = (pop) if @_ == 2 || (@_ && ref($_[0]) || ref(\$_[0]) eq 'GLOB'); $nntp->_HEAD(@_) ? $nntp->read_until_dot(@fh) : undef; } sub headfh { @_ >= 1 && @_ <= 2 or croak 'usage: $nntp->headfh( [ MSGID ] )'; my $nntp = shift; return unless $nntp->_HEAD(@_); return $nntp->tied_fh; } sub nntpstat { @_ == 1 || @_ == 2 or croak 'usage: $nntp->nntpstat( [ MSGID ] )'; my $nntp = shift; $nntp->_STAT(@_) && $nntp->message =~ /(<[^>]+>)/o ? $1 : undef; } sub group { @_ == 1 || @_ == 2 or croak 'usage: $nntp->group( [ GROUP ] )'; my $nntp = shift; my $grp = ${*$nntp}{'net_nntp_group'}; return $grp unless (@_ || wantarray); my $newgrp = shift; $newgrp = (defined($grp) and length($grp)) ? $grp : "" unless defined($newgrp) and length($newgrp); return unless $nntp->_GROUP($newgrp) and $nntp->message =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\S+)/; my ($count, $first, $last, $group) = ($1, $2, $3, $4); # group may be replied as '(current group)' $group = ${*$nntp}{'net_nntp_group'} if $group =~ /\(/; ${*$nntp}{'net_nntp_group'} = $group; wantarray ? ($count, $first, $last, $group) : $group; } sub help { @_ == 1 or croak 'usage: $nntp->help()'; my $nntp = shift; $nntp->_HELP ? $nntp->read_until_dot : undef; } sub ihave { @_ >= 2 or croak 'usage: $nntp->ihave( MESSAGE-ID [, MESSAGE ])'; my $nntp = shift; my $mid = shift; $nntp->_IHAVE($mid) && $nntp->datasend(@_) ? @_ == 0 || $nntp->dataend : undef; } sub last { @_ == 1 or croak 'usage: $nntp->last()'; my $nntp = shift; $nntp->_LAST && $nntp->message =~ /(<[^>]+>)/o ? $1 : undef; } sub list { @_ == 1 or croak 'usage: $nntp->list()'; my $nntp = shift; $nntp->_LIST ? $nntp->_grouplist : undef; } sub newgroups { @_ >= 2 or croak 'usage: $nntp->newgroups( SINCE [, DISTRIBUTIONS ])'; my $nntp = shift; my $time = _timestr(shift); my $dist = shift || ""; $dist = join(",", @{$dist}) if ref($dist); $nntp->_NEWGROUPS($time, $dist) ? $nntp->_grouplist : undef; } sub newnews { @_ >= 2 && @_ <= 4 or croak 'usage: $nntp->newnews( SINCE [, GROUPS [, DISTRIBUTIONS ]])'; my $nntp = shift; my $time = _timestr(shift); my $grp = @_ ? shift: $nntp->group; my $dist = shift || ""; $grp ||= "*"; $grp = join(",", @{$grp}) if ref($grp); $dist = join(",", @{$dist}) if ref($dist); $nntp->_NEWNEWS($grp, $time, $dist) ? $nntp->_articlelist : undef; } sub next { @_ == 1 or croak 'usage: $nntp->next()'; my $nntp = shift; $nntp->_NEXT && $nntp->message =~ /(<[^>]+>)/o ? $1 : undef; } sub post { @_ >= 1 or croak 'usage: $nntp->post( [ MESSAGE ] )'; my $nntp = shift; $nntp->_POST() && $nntp->datasend(@_) ? @_ == 0 || $nntp->dataend : undef; } sub postfh { my $nntp = shift; return unless $nntp->_POST(); return $nntp->tied_fh; } sub quit { @_ == 1 or croak 'usage: $nntp->quit()'; my $nntp = shift; $nntp->_QUIT; $nntp->close; } sub slave { @_ == 1 or croak 'usage: $nntp->slave()'; my $nntp = shift; $nntp->_SLAVE; } ## ## The following methods are not implemented by all servers ## sub active { @_ == 1 || @_ == 2 or croak 'usage: $nntp->active( [ PATTERN ] )'; my $nntp = shift; $nntp->_LIST('ACTIVE', @_) ? $nntp->_grouplist : undef; } sub active_times { @_ == 1 or croak 'usage: $nntp->active_times()'; my $nntp = shift; $nntp->_LIST('ACTIVE.TIMES') ? $nntp->_grouplist : undef; } sub distributions { @_ == 1 or croak 'usage: $nntp->distributions()'; my $nntp = shift; $nntp->_LIST('DISTRIBUTIONS') ? $nntp->_description : undef; } sub distribution_patterns { @_ == 1 or croak 'usage: $nntp->distributions()'; my $nntp = shift; my $arr; local $_; ## no critic (ControlStructures::ProhibitMutatingListFunctions) $nntp->_LIST('DISTRIB.PATS') && ($arr = $nntp->read_until_dot) ? [grep { /^\d/ && (chomp, $_ = [split /:/]) } @$arr] : undef; } sub newsgroups { @_ == 1 || @_ == 2 or croak 'usage: $nntp->newsgroups( [ PATTERN ] )'; my $nntp = shift; $nntp->_LIST('NEWSGROUPS', @_) ? $nntp->_description : undef; } sub overview_fmt { @_ == 1 or croak 'usage: $nntp->overview_fmt()'; my $nntp = shift; $nntp->_LIST('OVERVIEW.FMT') ? $nntp->_articlelist : undef; } sub subscriptions { @_ == 1 or croak 'usage: $nntp->subscriptions()'; my $nntp = shift; $nntp->_LIST('SUBSCRIPTIONS') ? $nntp->_articlelist : undef; } sub listgroup { @_ == 1 || @_ == 2 or croak 'usage: $nntp->listgroup( [ GROUP ] )'; my $nntp = shift; $nntp->_LISTGROUP(@_) ? $nntp->_articlelist : undef; } sub reader { @_ == 1 or croak 'usage: $nntp->reader()'; my $nntp = shift; $nntp->_MODE('READER'); } sub xgtitle { @_ == 1 || @_ == 2 or croak 'usage: $nntp->xgtitle( [ PATTERN ] )'; my $nntp = shift; $nntp->_XGTITLE(@_) ? $nntp->_description : undef; } sub xhdr { @_ >= 2 && @_ <= 4 or croak 'usage: $nntp->xhdr( HEADER, [ MESSAGE-SPEC ] )'; my $nntp = shift; my $hdr = shift; my $arg = _msg_arg(@_); $nntp->_XHDR($hdr, $arg) ? $nntp->_description : undef; } sub xover { @_ == 2 || @_ == 3 or croak 'usage: $nntp->xover( MESSAGE-SPEC )'; my $nntp = shift; my $arg = _msg_arg(@_); $nntp->_XOVER($arg) ? $nntp->_fieldlist : undef; } sub xpat { @_ == 4 || @_ == 5 or croak '$nntp->xpat( HEADER, PATTERN, MESSAGE-SPEC )'; my $nntp = shift; my $hdr = shift; my $pat = shift; my $arg = _msg_arg(@_); $pat = join(" ", @$pat) if ref($pat); $nntp->_XPAT($hdr, $arg, $pat) ? $nntp->_description : undef; } sub xpath { @_ == 2 or croak 'usage: $nntp->xpath( MESSAGE-ID )'; my ($nntp, $mid) = @_; return unless $nntp->_XPATH($mid); my $m; ($m = $nntp->message) =~ s/^\d+\s+//o; my @p = split /\s+/, $m; wantarray ? @p : $p[0]; } sub xrover { @_ == 2 || @_ == 3 or croak 'usage: $nntp->xrover( MESSAGE-SPEC )'; my $nntp = shift; my $arg = _msg_arg(@_); $nntp->_XROVER($arg) ? $nntp->_description : undef; } sub date { @_ == 1 or croak 'usage: $nntp->date()'; my $nntp = shift; $nntp->_DATE && $nntp->message =~ /(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ ? timegm($6, $5, $4, $3, $2 - 1, $1 - 1900) : undef; } ## ## Private subroutines ## sub _msg_arg { my $spec = shift; my $arg = ""; if (@_) { carp "Depriciated passing of two message numbers, " . "pass a reference" if $^W; $spec = [$spec, $_[0]]; } if (defined $spec) { if (ref($spec)) { $arg = $spec->[0]; if (defined $spec->[1]) { $arg .= "-" if $spec->[1] != $spec->[0]; $arg .= $spec->[1] if $spec->[1] > $spec->[0]; } } else { $arg = $spec; } } $arg; } sub _timestr { my $time = shift; my @g = reverse((gmtime($time))[0 .. 5]); $g[1] += 1; $g[0] %= 100; sprintf "%02d%02d%02d %02d%02d%02d GMT", @g; } sub _grouplist { my $nntp = shift; my $arr = $nntp->read_until_dot or return; my $hash = {}; foreach my $ln (@$arr) { my @a = split(/[\s\n]+/, $ln); $hash->{$a[0]} = [@a[1, 2, 3]]; } $hash; } sub _fieldlist { my $nntp = shift; my $arr = $nntp->read_until_dot or return; my $hash = {}; foreach my $ln (@$arr) { my @a = split(/[\t\n]/, $ln); my $m = shift @a; $hash->{$m} = [@a]; } $hash; } sub _articlelist { my $nntp = shift; my $arr = $nntp->read_until_dot; chomp(@$arr) if $arr; $arr; } sub _description { my $nntp = shift; my $arr = $nntp->read_until_dot or return; my $hash = {}; foreach my $ln (@$arr) { chomp($ln); $hash->{$1} = $ln if $ln =~ s/^\s*(\S+)\s*//o; } $hash; } ## ## The commands ## sub _ARTICLE { shift->command('ARTICLE', @_)->response == CMD_OK } sub _AUTHINFO { shift->command('AUTHINFO', @_)->response } sub _BODY { shift->command('BODY', @_)->response == CMD_OK } sub _DATE { shift->command('DATE')->response == CMD_INFO } sub _GROUP { shift->command('GROUP', @_)->response == CMD_OK } sub _HEAD { shift->command('HEAD', @_)->response == CMD_OK } sub _HELP { shift->command('HELP', @_)->response == CMD_INFO } sub _IHAVE { shift->command('IHAVE', @_)->response == CMD_MORE } sub _LAST { shift->command('LAST')->response == CMD_OK } sub _LIST { shift->command('LIST', @_)->response == CMD_OK } sub _LISTGROUP { shift->command('LISTGROUP', @_)->response == CMD_OK } sub _NEWGROUPS { shift->command('NEWGROUPS', @_)->response == CMD_OK } sub _NEWNEWS { shift->command('NEWNEWS', @_)->response == CMD_OK } sub _NEXT { shift->command('NEXT')->response == CMD_OK } sub _POST { shift->command('POST', @_)->response == CMD_MORE } sub _QUIT { shift->command('QUIT', @_)->response == CMD_OK } sub _SLAVE { shift->command('SLAVE', @_)->response == CMD_OK } sub _STARTTLS { shift->command("STARTTLS")->response() == CMD_MORE } sub _STAT { shift->command('STAT', @_)->response == CMD_OK } sub _MODE { shift->command('MODE', @_)->response == CMD_OK } sub _XGTITLE { shift->command('XGTITLE', @_)->response == CMD_OK } sub _XHDR { shift->command('XHDR', @_)->response == CMD_OK } sub _XPAT { shift->command('XPAT', @_)->response == CMD_OK } sub _XPATH { shift->command('XPATH', @_)->response == CMD_OK } sub _XOVER { shift->command('XOVER', @_)->response == CMD_OK } sub _XROVER { shift->command('XROVER', @_)->response == CMD_OK } sub _XTHREAD { shift->unsupported } sub _XSEARCH { shift->unsupported } sub _XINDEX { shift->unsupported } ## ## IO/perl methods ## sub DESTROY { my $nntp = shift; defined(fileno($nntp)) && $nntp->quit; } { package Net::NNTP::_SSL; our @ISA = ( $ssl_class ? ($ssl_class):(), 'Net::NNTP' ); sub starttls { die "NNTP connection is already in SSL mode" } sub start_SSL { my ($class,$nntp,%arg) = @_; delete @arg{ grep { !m{^SSL_} } keys %arg }; ( $arg{SSL_verifycn_name} ||= $nntp->host ) =~s{(?can_client_sni; my $ok = $class->SUPER::start_SSL($nntp, SSL_verifycn_scheme => 'nntp', %arg ); $@ = $ssl_class->errstr if !$ok; return $ok; } } 1; __END__ =head1 NAME Net::NNTP - NNTP Client class =head1 SYNOPSIS use Net::NNTP; $nntp = Net::NNTP->new("some.host.name"); $nntp->quit; # start with SSL, e.g. nntps $nntp = Net::NNTP->new("some.host.name", SSL => 1); # start with plain and upgrade to SSL $nntp = Net::NNTP->new("some.host.name"); $nntp->starttls; =head1 DESCRIPTION C is a class implementing a simple NNTP client in Perl as described in RFC977 and RFC4642. With L installed it also provides support for implicit and explicit TLS encryption, i.e. NNTPS or NNTP+STARTTLS. The Net::NNTP class is a subclass of Net::Cmd and (depending on avaibility) of IO::Socket::IP, IO::Socket::INET6 or IO::Socket::INET. =head1 CONSTRUCTOR =over 4 =item new ( [ HOST ] [, OPTIONS ]) This is the constructor for a new Net::NNTP object. C is the name of the remote host to which a NNTP connection is required. If not given then it may be passed as the C option described below. If no host is passed then two environment variables are checked, first C then C, then C is checked, and if a host is not found then C is used. C are passed in a hash like fashion, using key and value pairs. Possible options are: B - NNTP host to connect to. It may be a single scalar, as defined for the C option in L, or a reference to an array with hosts to try in turn. The L method will return the value which was used to connect to the host. B - port to connect to. Default - 119 for plain NNTP and 563 for immediate SSL (nntps). B - If the connection should be done from start with SSL, contrary to later upgrade with C. You can use SSL arguments as documented in L, but it will usually use the right arguments already. B - Maximum time, in seconds, to wait for a response from the NNTP server, a value of zero will cause all IO operations to block. (default: 120) B - Enable the printing of debugging information to STDERR B - If the remote server is INN then initially the connection will be to innd, by default C will issue a C command so that the remote server becomes nnrpd. If the C option is given with a value of zero, then this command will not be sent and the connection will be left talking to innd. B and B - These parameters are passed directly to IO::Socket to allow binding the socket to a specific local address and port. B - This parameter is passed directly to IO::Socket and makes it possible to enforce IPv4 connections even if L is used as super class. Alternatively B can be used. =back =head1 METHODS Unless otherwise stated all methods return either a I or I value, with I meaning that the operation was a success. When a method states that it returns a value, failure will be returned as I or an empty list. C inherits from C so methods defined in C may be used to send commands to the remote NNTP server in addition to the methods documented here. =over 4 =item host () Returns the value used by the constructor, and passed to IO::Socket::INET, to connect to the host. =item starttls () Upgrade existing plain connection to SSL. Any arguments necessary for SSL must be given in C already. =item article ( [ MSGID|MSGNUM ], [FH] ) Retrieve the header, a blank line, then the body (text) of the specified article. If C is specified then it is expected to be a valid filehandle and the result will be printed to it, on success a true value will be returned. If C is not specified then the return value, on success, will be a reference to an array containing the article requested, each entry in the array will contain one line of the article. If no arguments are passed then the current article in the currently selected newsgroup is fetched. C is a numeric id of an article in the current newsgroup, and will change the current article pointer. C is the message id of an article as shown in that article's header. It is anticipated that the client will obtain the C from a list provided by the C command, from references contained within another article, or from the message-id provided in the response to some other commands. If there is an error then C will be returned. =item body ( [ MSGID|MSGNUM ], [FH] ) Like C
but only fetches the body of the article. =item head ( [ MSGID|MSGNUM ], [FH] ) Like C
but only fetches the headers for the article. =item articlefh ( [ MSGID|MSGNUM ] ) =item bodyfh ( [ MSGID|MSGNUM ] ) =item headfh ( [ MSGID|MSGNUM ] ) These are similar to article(), body() and head(), but rather than returning the requested data directly, they return a tied filehandle from which to read the article. =item nntpstat ( [ MSGID|MSGNUM ] ) The C command is similar to the C
command except that no text is returned. When selecting by message number within a group, the C command serves to set the "current article pointer" without sending text. Using the C command to select by message-id is valid but of questionable value, since a selection by message-id does B alter the "current article pointer". Returns the message-id of the "current article". =item group ( [ GROUP ] ) Set and/or get the current group. If C is not given then information is returned on the current group. In a scalar context it returns the group name. In an array context the return value is a list containing, the number of articles in the group, the number of the first article, the number of the last article and the group name. =item help ( ) Request help text (a short summary of commands that are understood by this implementation) from the server. Returns the text or undef upon failure. =item ihave ( MSGID [, MESSAGE ]) The C command informs the server that the client has an article whose id is C. If the server desires a copy of that article and C has been given then it will be sent. Returns I if the server desires the article and C was successfully sent, if specified. If C is not specified then the message must be sent using the C and C methods from L C can be either an array of lines or a reference to an array and must be encoded by the caller to octets of whatever encoding is required, e.g. by using the Encode module's C function. =item last () Set the "current article pointer" to the previous article in the current newsgroup. Returns the message-id of the article. =item date () Returns the date on the remote server. This date will be in a UNIX time format (seconds since 1970) =item postok () C will return I if the servers initial response indicated that it will allow posting. =item authinfo ( USER, PASS ) Authenticates to the server (using the original AUTHINFO USER / AUTHINFO PASS form, defined in RFC2980) using the supplied username and password. Please note that the password is sent in clear text to the server. This command should not be used with valuable passwords unless the connection to the server is somehow protected. =item authinfo_simple ( USER, PASS ) Authenticates to the server (using the proposed NNTP V2 AUTHINFO SIMPLE form, defined and deprecated in RFC2980) using the supplied username and password. As with L the password is sent in clear text. =item list () Obtain information about all the active newsgroups. The results is a reference to a hash where the key is a group name and each value is a reference to an array. The elements in this array are:- the last article number in the group, the first article number in the group and any information flags about the group. =item newgroups ( SINCE [, DISTRIBUTIONS ]) C is a time value and C is either a distribution pattern or a reference to a list of distribution patterns. The result is the same as C, but the groups return will be limited to those created after C and, if specified, in one of the distribution areas in C. =item newnews ( SINCE [, GROUPS [, DISTRIBUTIONS ]]) C is a time value. C is either a group pattern or a reference to a list of group patterns. C is either a distribution pattern or a reference to a list of distribution patterns. Returns a reference to a list which contains the message-ids of all news posted after C, that are in a groups which matched C and a distribution which matches C. =item next () Set the "current article pointer" to the next article in the current newsgroup. Returns the message-id of the article. =item post ( [ MESSAGE ] ) Post a new article to the news server. If C is specified and posting is allowed then the message will be sent. If C is not specified then the message must be sent using the C and C methods from L C can be either an array of lines or a reference to an array and must be encoded by the caller to octets of whatever encoding is required, e.g. by using the Encode module's C function. The message, either sent via C or as the C parameter, must be in the format as described by RFC822 and must contain From:, Newsgroups: and Subject: headers. =item postfh () Post a new article to the news server using a tied filehandle. If posting is allowed, this method will return a tied filehandle that you can print() the contents of the article to be posted. You must explicitly close() the filehandle when you are finished posting the article, and the return value from the close() call will indicate whether the message was successfully posted. =item slave () Tell the remote server that I am not a user client, but probably another news server. =item quit () Quit the remote server and close the socket connection. =item can_inet6 () Returns whether we can use IPv6. =item can_ssl () Returns whether we can use SSL. =back =head2 Extension methods These methods use commands that are not part of the RFC977 documentation. Some servers may not support all of them. =over 4 =item newsgroups ( [ PATTERN ] ) Returns a reference to a hash where the keys are all the group names which match C, or all of the groups if no pattern is specified, and each value contains the description text for the group. =item distributions () Returns a reference to a hash where the keys are all the possible distribution names and the values are the distribution descriptions. =item distribution_patterns () Returns a reference to an array where each element, itself an array reference, consists of the three fields of a line of the distrib.pats list maintained by some NNTP servers, namely: a weight, a wildmat and a value which the client may use to construct a Distribution header. =item subscriptions () Returns a reference to a list which contains a list of groups which are recommended for a new user to subscribe to. =item overview_fmt () Returns a reference to an array which contain the names of the fields returned by C. =item active_times () Returns a reference to a hash where the keys are the group names and each value is a reference to an array containing the time the groups was created and an identifier, possibly an Email address, of the creator. =item active ( [ PATTERN ] ) Similar to C but only active groups that match the pattern are returned. C can be a group pattern. =item xgtitle ( PATTERN ) Returns a reference to a hash where the keys are all the group names which match C and each value is the description text for the group. =item xhdr ( HEADER, MESSAGE-SPEC ) Obtain the header field C
for all the messages specified. The return value will be a reference to a hash where the keys are the message numbers and each value contains the text of the requested header for that message. =item xover ( MESSAGE-SPEC ) The return value will be a reference to a hash where the keys are the message numbers and each value contains a reference to an array which contains the overview fields for that message. The names of the fields can be obtained by calling C. =item xpath ( MESSAGE-ID ) Returns the path name to the file on the server which contains the specified message. =item xpat ( HEADER, PATTERN, MESSAGE-SPEC) The result is the same as C except the is will be restricted to headers where the text of the header matches C =item xrover () The XROVER command returns reference information for the article(s) specified. Returns a reference to a HASH where the keys are the message numbers and the values are the References: lines from the articles =item listgroup ( [ GROUP ] ) Returns a reference to a list of all the active messages in C, or the current group if C is not specified. =item reader () Tell the server that you are a reader and not another server. This is required by some servers. For example if you are connecting to an INN server and you have transfer permission your connection will be connected to the transfer daemon, not the NNTP daemon. Issuing this command will cause the transfer daemon to hand over control to the NNTP daemon. Some servers do not understand this command, but issuing it and ignoring the response is harmless. =back =head1 UNSUPPORTED The following NNTP command are unsupported by the package, and there are no plans to do so. AUTHINFO GENERIC XTHREAD XSEARCH XINDEX =head1 DEFINITIONS =over 4 =item MESSAGE-SPEC C is either a single message-id, a single message number, or a reference to a list of two message numbers. If C is a reference to a list of two message numbers and the second number in a range is less than or equal to the first then the range represents all messages in the group after the first message number. B For compatibility reasons only with earlier versions of Net::NNTP a message spec can be passed as a list of two numbers, this is deprecated and a reference to the list should now be passed =item PATTERN The C protocol uses the C format for patterns. The WILDMAT format was first developed by Rich Salz based on the format used in the UNIX "find" command to articulate file names. It was developed to provide a uniform mechanism for matching patterns in the same manner that the UNIX shell matches filenames. Patterns are implicitly anchored at the beginning and end of each string when testing for a match. There are five pattern matching operations other than a strict one-to-one match between the pattern and the source to be checked for a match. The first is an asterisk C<*> to match any sequence of zero or more characters. The second is a question mark C to match any single character. The third specifies a specific set of characters. The set is specified as a list of characters, or as a range of characters where the beginning and end of the range are separated by a minus (or dash) character, or as any combination of lists and ranges. The dash can also be included in the set as a character it if is the beginning or end of the set. This set is enclosed in square brackets. The close square bracket C<]> may be used in a set if it is the first character in the set. The fourth operation is the same as the logical not of the third operation and is specified the same way as the third with the addition of a caret character C<^> at the beginning of the test string just inside the open square bracket. The final operation uses the backslash character to invalidate the special meaning of an open square bracket C<[>, the asterisk, backslash or the question mark. Two backslashes in sequence will result in the evaluation of the backslash as a character with no special meaning. =over 4 =item Examples =item C<[^]-]> matches any single character other than a close square bracket or a minus sign/dash. =item C<*bdc> matches any string that ends with the string "bdc" including the string "bdc" (without quotes). =item C<[0-9a-zA-Z]> matches any single printable alphanumeric ASCII character. =item C matches any four character string which begins with a and ends with d. =back =back =head1 SEE ALSO L, L =head1 AUTHOR Graham Barr EFE. Steve Hay EFE is now maintaining libnet as of version 1.22_02. =head1 COPYRIGHT Copyright (C) 1995-1997 Graham Barr. All rights reserved. Copyright (C) 2013-2016 Steve Hay. All rights reserved. =head1 LICENCE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e. under the terms of either the GNU General Public License or the Artistic License, as specified in the F file. =cut PK f1]s:ppSMTP.pmnu[# Net::SMTP.pm # # Copyright (C) 1995-2004 Graham Barr. All rights reserved. # Copyright (C) 2013-2016 Steve Hay. All rights reserved. # This module is free software; you can redistribute it and/or modify it under # the same terms as Perl itself, i.e. under the terms of either the GNU General # Public License or the Artistic License, as specified in the F file. package Net::SMTP; use 5.008001; use strict; use warnings; use Carp; use IO::Socket; use Net::Cmd; use Net::Config; use Socket; our $VERSION = "3.11"; # Code for detecting if we can use SSL my $ssl_class = eval { require IO::Socket::SSL; # first version with default CA on most platforms no warnings 'numeric'; IO::Socket::SSL->VERSION(2.007); } && 'IO::Socket::SSL'; my $nossl_warn = !$ssl_class && 'To use SSL please install IO::Socket::SSL with version>=2.007'; # Code for detecting if we can use IPv6 my $family_key = 'Domain'; my $inet6_class = eval { require IO::Socket::IP; no warnings 'numeric'; IO::Socket::IP->VERSION(0.25) || die; $family_key = 'Family'; } && 'IO::Socket::IP' || eval { require IO::Socket::INET6; no warnings 'numeric'; IO::Socket::INET6->VERSION(2.62); } && 'IO::Socket::INET6'; sub can_ssl { $ssl_class }; sub can_inet6 { $inet6_class }; our @ISA = ('Net::Cmd', $inet6_class || 'IO::Socket::INET'); sub new { my $self = shift; my $type = ref($self) || $self; my ($host, %arg); if (@_ % 2) { $host = shift; %arg = @_; } else { %arg = @_; $host = delete $arg{Host}; } if ($arg{SSL}) { # SSL from start die $nossl_warn if !$ssl_class; $arg{Port} ||= 465; } my $hosts = defined $host ? $host : $NetConfig{smtp_hosts}; my $obj; $arg{Timeout} = 120 if ! defined $arg{Timeout}; foreach my $h (@{ref($hosts) ? $hosts : [$hosts]}) { $obj = $type->SUPER::new( PeerAddr => ($host = $h), PeerPort => $arg{Port} || 'smtp(25)', LocalAddr => $arg{LocalAddr}, LocalPort => $arg{LocalPort}, $family_key => $arg{Domain} || $arg{Family}, Proto => 'tcp', Timeout => $arg{Timeout} ) and last; } return unless defined $obj; ${*$obj}{'net_smtp_arg'} = \%arg; ${*$obj}{'net_smtp_host'} = $host; if ($arg{SSL}) { Net::SMTP::_SSL->start_SSL($obj,%arg) or return; } $obj->autoflush(1); $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef); unless ($obj->response() == CMD_OK) { my $err = ref($obj) . ": " . $obj->code . " " . $obj->message; $obj->close(); $@ = $err; return; } ${*$obj}{'net_smtp_exact_addr'} = $arg{ExactAddresses}; (${*$obj}{'net_smtp_banner'}) = $obj->message; (${*$obj}{'net_smtp_domain'}) = $obj->message =~ /\A\s*(\S+)/; if (!exists $arg{SendHello} || $arg{SendHello}) { unless ($obj->hello($arg{Hello} || "")) { my $err = ref($obj) . ": " . $obj->code . " " . $obj->message; $obj->close(); $@ = $err; return; } } $obj; } sub host { my $me = shift; ${*$me}{'net_smtp_host'}; } ## ## User interface methods ## sub banner { my $me = shift; return ${*$me}{'net_smtp_banner'} || undef; } sub domain { my $me = shift; return ${*$me}{'net_smtp_domain'} || undef; } sub etrn { my $self = shift; defined($self->supports('ETRN', 500, ["Command unknown: 'ETRN'"])) && $self->_ETRN(@_); } sub auth { my ($self, $username, $password) = @_; eval { require MIME::Base64; require Authen::SASL; } or $self->set_status(500, ["Need MIME::Base64 and Authen::SASL todo auth"]), return 0; my $mechanisms = $self->supports('AUTH', 500, ["Command unknown: 'AUTH'"]); return unless defined $mechanisms; my $sasl; if (ref($username) and UNIVERSAL::isa($username, 'Authen::SASL')) { $sasl = $username; my $requested_mechanisms = $sasl->mechanism(); if (! defined($requested_mechanisms) || $requested_mechanisms eq '') { $sasl->mechanism($mechanisms); } } else { die "auth(username, password)" if not length $username; $sasl = Authen::SASL->new( mechanism => $mechanisms, callback => { user => $username, pass => $password, authname => $username, }, debug => $self->debug ); } my $client; my $str; do { if ($client) { # $client mechanism failed, so we need to exclude this mechanism from list my $failed_mechanism = $client->mechanism; return unless defined $failed_mechanism; $self->debug_text("Auth mechanism failed: $failed_mechanism") if $self->debug; $mechanisms =~ s/\b\Q$failed_mechanism\E\b//; return unless $mechanisms =~ /\S/; $sasl->mechanism($mechanisms); } # We should probably allow the user to pass the host, but I don't # currently know and SASL mechanisms that are used by smtp that need it $client = $sasl->client_new('smtp', ${*$self}{'net_smtp_host'}, 0); $str = $client->client_start; } while (!defined $str); # We don't support sasl mechanisms that encrypt the socket traffic. # todo that we would really need to change the ISA hierarchy # so we don't inherit from IO::Socket, but instead hold it in an attribute my @cmd = ("AUTH", $client->mechanism); my $code; push @cmd, MIME::Base64::encode_base64($str, '') if defined $str and length $str; while (($code = $self->command(@cmd)->response()) == CMD_MORE) { my $str2 = MIME::Base64::decode_base64(($self->message)[0]); $self->debug_print(0, "(decoded) " . $str2 . "\n") if $self->debug; $str = $client->client_step($str2); @cmd = ( MIME::Base64::encode_base64($str, '') ); $self->debug_print(1, "(decoded) " . $str . "\n") if $self->debug; } $code == CMD_OK; } sub hello { my $me = shift; my $domain = shift || "localhost.localdomain"; my $ok = $me->_EHLO($domain); my @msg = $me->message; if ($ok) { my $h = ${*$me}{'net_smtp_esmtp'} = {}; foreach my $ln (@msg) { $h->{uc $1} = $2 if $ln =~ /([-\w]+)\b[= \t]*([^\n]*)/; } } elsif ($me->status == CMD_ERROR) { @msg = $me->message if $ok = $me->_HELO($domain); } return unless $ok; ${*$me}{net_smtp_hello_domain} = $domain; $msg[0] =~ /\A\s*(\S+)/; return ($1 || " "); } sub starttls { my $self = shift; $ssl_class or die $nossl_warn; $self->_STARTTLS or return; Net::SMTP::_SSL->start_SSL($self, %{ ${*$self}{'net_smtp_arg'} }, # (ssl) args given in new @_ # more (ssl) args ) or return; # another hello after starttls to read new ESMTP capabilities return $self->hello(${*$self}{net_smtp_hello_domain}); } sub supports { my $self = shift; my $cmd = uc shift; return ${*$self}{'net_smtp_esmtp'}->{$cmd} if exists ${*$self}{'net_smtp_esmtp'}->{$cmd}; $self->set_status(@_) if @_; return; } sub _addr { my $self = shift; my $addr = shift; $addr = "" unless defined $addr; if (${*$self}{'net_smtp_exact_addr'}) { return $1 if $addr =~ /^\s*(<.*>)\s*$/s; } else { return $1 if $addr =~ /(<[^>]*>)/; $addr =~ s/^\s+|\s+$//sg; } "<$addr>"; } sub mail { my $me = shift; my $addr = _addr($me, shift); my $opts = ""; if (@_) { my %opt = @_; my ($k, $v); if (exists ${*$me}{'net_smtp_esmtp'}) { my $esmtp = ${*$me}{'net_smtp_esmtp'}; if (defined($v = delete $opt{Size})) { if (exists $esmtp->{SIZE}) { $opts .= sprintf " SIZE=%d", $v + 0; } else { carp 'Net::SMTP::mail: SIZE option not supported by host'; } } if (defined($v = delete $opt{Return})) { if (exists $esmtp->{DSN}) { $opts .= " RET=" . ((uc($v) eq "FULL") ? "FULL" : "HDRS"); } else { carp 'Net::SMTP::mail: DSN option not supported by host'; } } if (defined($v = delete $opt{Bits})) { if ($v eq "8") { if (exists $esmtp->{'8BITMIME'}) { $opts .= " BODY=8BITMIME"; } else { carp 'Net::SMTP::mail: 8BITMIME option not supported by host'; } } elsif ($v eq "binary") { if (exists $esmtp->{'BINARYMIME'} && exists $esmtp->{'CHUNKING'}) { $opts .= " BODY=BINARYMIME"; ${*$me}{'net_smtp_chunking'} = 1; } else { carp 'Net::SMTP::mail: BINARYMIME option not supported by host'; } } elsif (exists $esmtp->{'8BITMIME'} or exists $esmtp->{'BINARYMIME'}) { $opts .= " BODY=7BIT"; } else { carp 'Net::SMTP::mail: 8BITMIME and BINARYMIME options not supported by host'; } } if (defined($v = delete $opt{Transaction})) { if (exists $esmtp->{CHECKPOINT}) { $opts .= " TRANSID=" . _addr($me, $v); } else { carp 'Net::SMTP::mail: CHECKPOINT option not supported by host'; } } if (defined($v = delete $opt{Envelope})) { if (exists $esmtp->{DSN}) { $v =~ s/([^\041-\176]|=|\+)/sprintf "+%02X", ord($1)/sge; $opts .= " ENVID=$v"; } else { carp 'Net::SMTP::mail: DSN option not supported by host'; } } if (defined($v = delete $opt{ENVID})) { # expected to be in a format as required by RFC 3461, xtext-encoded if (exists $esmtp->{DSN}) { $opts .= " ENVID=$v"; } else { carp 'Net::SMTP::mail: DSN option not supported by host'; } } if (defined($v = delete $opt{AUTH})) { # expected to be in a format as required by RFC 2554, # rfc2821-quoted and xtext-encoded, or <> if (exists $esmtp->{AUTH}) { $v = '<>' if !defined($v) || $v eq ''; $opts .= " AUTH=$v"; } else { carp 'Net::SMTP::mail: AUTH option not supported by host'; } } if (defined($v = delete $opt{XVERP})) { if (exists $esmtp->{'XVERP'}) { $opts .= " XVERP"; } else { carp 'Net::SMTP::mail: XVERP option not supported by host'; } } carp 'Net::SMTP::recipient: unknown option(s) ' . join(" ", keys %opt) . ' - ignored' if scalar keys %opt; } else { carp 'Net::SMTP::mail: ESMTP not supported by host - options discarded :-('; } } $me->_MAIL("FROM:" . $addr . $opts); } sub send { my $me = shift; $me->_SEND("FROM:" . _addr($me, $_[0])) } sub send_or_mail { my $me = shift; $me->_SOML("FROM:" . _addr($me, $_[0])) } sub send_and_mail { my $me = shift; $me->_SAML("FROM:" . _addr($me, $_[0])) } sub reset { my $me = shift; $me->dataend() if (exists ${*$me}{'net_smtp_lastch'}); $me->_RSET(); } sub recipient { my $smtp = shift; my $opts = ""; my $skip_bad = 0; if (@_ && ref($_[-1])) { my %opt = %{pop(@_)}; my $v; $skip_bad = delete $opt{'SkipBad'}; if (exists ${*$smtp}{'net_smtp_esmtp'}) { my $esmtp = ${*$smtp}{'net_smtp_esmtp'}; if (defined($v = delete $opt{Notify})) { if (exists $esmtp->{DSN}) { $opts .= " NOTIFY=" . join(",", map { uc $_ } @$v); } else { carp 'Net::SMTP::recipient: DSN option not supported by host'; } } if (defined($v = delete $opt{ORcpt})) { if (exists $esmtp->{DSN}) { $opts .= " ORCPT=" . $v; } else { carp 'Net::SMTP::recipient: DSN option not supported by host'; } } carp 'Net::SMTP::recipient: unknown option(s) ' . join(" ", keys %opt) . ' - ignored' if scalar keys %opt; } elsif (%opt) { carp 'Net::SMTP::recipient: ESMTP not supported by host - options discarded :-('; } } my @ok; foreach my $addr (@_) { if ($smtp->_RCPT("TO:" . _addr($smtp, $addr) . $opts)) { push(@ok, $addr) if $skip_bad; } elsif (!$skip_bad) { return 0; } } return $skip_bad ? @ok : 1; } BEGIN { *to = \&recipient; *cc = \&recipient; *bcc = \&recipient; } sub data { my $me = shift; if (exists ${*$me}{'net_smtp_chunking'}) { carp 'Net::SMTP::data: CHUNKING extension in use, must call bdat instead'; } else { my $ok = $me->_DATA() && $me->datasend(@_); $ok && @_ ? $me->dataend : $ok; } } sub bdat { my $me = shift; if (exists ${*$me}{'net_smtp_chunking'}) { my $data = shift; $me->_BDAT(length $data) && $me->rawdatasend($data) && $me->response() == CMD_OK; } else { carp 'Net::SMTP::bdat: CHUNKING extension is not in use, call data instead'; } } sub bdatlast { my $me = shift; if (exists ${*$me}{'net_smtp_chunking'}) { my $data = shift; $me->_BDAT(length $data, "LAST") && $me->rawdatasend($data) && $me->response() == CMD_OK; } else { carp 'Net::SMTP::bdat: CHUNKING extension is not in use, call data instead'; } } sub datafh { my $me = shift; return unless $me->_DATA(); return $me->tied_fh; } sub expand { my $me = shift; $me->_EXPN(@_) ? ($me->message) : (); } sub verify { shift->_VRFY(@_) } sub help { my $me = shift; $me->_HELP(@_) ? scalar $me->message : undef; } sub quit { my $me = shift; $me->_QUIT; $me->close; } sub DESTROY { # ignore } ## ## RFC821 commands ## sub _EHLO { shift->command("EHLO", @_)->response() == CMD_OK } sub _HELO { shift->command("HELO", @_)->response() == CMD_OK } sub _MAIL { shift->command("MAIL", @_)->response() == CMD_OK } sub _RCPT { shift->command("RCPT", @_)->response() == CMD_OK } sub _SEND { shift->command("SEND", @_)->response() == CMD_OK } sub _SAML { shift->command("SAML", @_)->response() == CMD_OK } sub _SOML { shift->command("SOML", @_)->response() == CMD_OK } sub _VRFY { shift->command("VRFY", @_)->response() == CMD_OK } sub _EXPN { shift->command("EXPN", @_)->response() == CMD_OK } sub _HELP { shift->command("HELP", @_)->response() == CMD_OK } sub _RSET { shift->command("RSET")->response() == CMD_OK } sub _NOOP { shift->command("NOOP")->response() == CMD_OK } sub _QUIT { shift->command("QUIT")->response() == CMD_OK } sub _DATA { shift->command("DATA")->response() == CMD_MORE } sub _BDAT { shift->command("BDAT", @_) } sub _TURN { shift->unsupported(@_); } sub _ETRN { shift->command("ETRN", @_)->response() == CMD_OK } sub _AUTH { shift->command("AUTH", @_)->response() == CMD_OK } sub _STARTTLS { shift->command("STARTTLS")->response() == CMD_OK } { package Net::SMTP::_SSL; our @ISA = ( $ssl_class ? ($ssl_class):(), 'Net::SMTP' ); sub starttls { die "SMTP connection is already in SSL mode" } sub start_SSL { my ($class,$smtp,%arg) = @_; delete @arg{ grep { !m{^SSL_} } keys %arg }; ( $arg{SSL_verifycn_name} ||= $smtp->host ) =~s{(?can_client_sni; $arg{SSL_verifycn_scheme} ||= 'smtp'; my $ok = $class->SUPER::start_SSL($smtp,%arg); $@ = $ssl_class->errstr if !$ok; return $ok; } } 1; __END__ =head1 NAME Net::SMTP - Simple Mail Transfer Protocol Client =head1 SYNOPSIS use Net::SMTP; # Constructors $smtp = Net::SMTP->new('mailhost'); $smtp = Net::SMTP->new('mailhost', Timeout => 60); =head1 DESCRIPTION This module implements a client interface to the SMTP and ESMTP protocol, enabling a perl5 application to talk to SMTP servers. This documentation assumes that you are familiar with the concepts of the SMTP protocol described in RFC2821. With L installed it also provides support for implicit and explicit TLS encryption, i.e. SMTPS or SMTP+STARTTLS. The Net::SMTP class is a subclass of Net::Cmd and (depending on avaibility) of IO::Socket::IP, IO::Socket::INET6 or IO::Socket::INET. =head1 EXAMPLES This example prints the mail domain name of the SMTP server known as mailhost: #!/usr/local/bin/perl -w use Net::SMTP; $smtp = Net::SMTP->new('mailhost'); print $smtp->domain,"\n"; $smtp->quit; This example sends a small message to the postmaster at the SMTP server known as mailhost: #!/usr/local/bin/perl -w use Net::SMTP; my $smtp = Net::SMTP->new('mailhost'); $smtp->mail($ENV{USER}); if ($smtp->to('postmaster')) { $smtp->data(); $smtp->datasend("To: postmaster\n"); $smtp->datasend("\n"); $smtp->datasend("A simple test message\n"); $smtp->dataend(); } else { print "Error: ", $smtp->message(); } $smtp->quit; =head1 CONSTRUCTOR =over 4 =item new ( [ HOST ] [, OPTIONS ] ) This is the constructor for a new Net::SMTP object. C is the name of the remote host to which an SMTP connection is required. On failure C will be returned and C<$@> will contain the reason for the failure. C is optional. If C is not given then it may instead be passed as the C option described below. If neither is given then the C specified in C will be used. C are passed in a hash like fashion, using key and value pairs. Possible options are: B - SMTP requires that you identify yourself. This option specifies a string to pass as your mail domain. If not given localhost.localdomain will be used. B - If false then the EHLO (or HELO) command that is normally sent when constructing the object will not be sent. In that case the command will have to be sent manually by calling C instead. B - SMTP host to connect to. It may be a single scalar (hostname[:port]), as defined for the C option in L, or a reference to an array with hosts to try in turn. The L method will return the value which was used to connect to the host. Format - C from L new method. B - port to connect to. Default - 25 for plain SMTP and 465 for immediate SSL. B - If the connection should be done from start with SSL, contrary to later upgrade with C. You can use SSL arguments as documented in L, but it will usually use the right arguments already. B and B - These parameters are passed directly to IO::Socket to allow binding the socket to a specific local address and port. B - This parameter is passed directly to IO::Socket and makes it possible to enforce IPv4 connections even if L is used as super class. Alternatively B can be used. B - Maximum time, in seconds, to wait for a response from the SMTP server (default: 120) B - If true the all ADDRESS arguments must be as defined by C in RFC2822. If not given, or false, then Net::SMTP will attempt to extract the address from the value passed. B - Enable debugging information Example: $smtp = Net::SMTP->new('mailhost', Hello => 'my.mail.domain', Timeout => 30, Debug => 1, ); # the same $smtp = Net::SMTP->new( Host => 'mailhost', Hello => 'my.mail.domain', Timeout => 30, Debug => 1, ); # the same with direct SSL $smtp = Net::SMTP->new('mailhost', Hello => 'my.mail.domain', Timeout => 30, Debug => 1, SSL => 1, ); # Connect to the default server from Net::config $smtp = Net::SMTP->new( Hello => 'my.mail.domain', Timeout => 30, ); =back =head1 METHODS Unless otherwise stated all methods return either a I or I value, with I meaning that the operation was a success. When a method states that it returns a value, failure will be returned as I or an empty list. C inherits from C so methods defined in C may be used to send commands to the remote SMTP server in addition to the methods documented here. =over 4 =item banner () Returns the banner message which the server replied with when the initial connection was made. =item domain () Returns the domain that the remote SMTP server identified itself as during connection. =item hello ( DOMAIN ) Tell the remote server the mail domain which you are in using the EHLO command (or HELO if EHLO fails). Since this method is invoked automatically when the Net::SMTP object is constructed the user should normally not have to call it manually. =item host () Returns the value used by the constructor, and passed to IO::Socket::INET, to connect to the host. =item etrn ( DOMAIN ) Request a queue run for the DOMAIN given. =item starttls ( SSLARGS ) Upgrade existing plain connection to SSL. You can use SSL arguments as documented in L, but it will usually use the right arguments already. =item auth ( USERNAME, PASSWORD ) =item auth ( SASL ) Attempt SASL authentication. Requires Authen::SASL module. The first form constructs a new Authen::SASL object using the given username and password; the second form uses the given Authen::SASL object. =item mail ( ADDRESS [, OPTIONS] ) =item send ( ADDRESS ) =item send_or_mail ( ADDRESS ) =item send_and_mail ( ADDRESS ) Send the appropriate command to the server MAIL, SEND, SOML or SAML. C
is the address of the sender. This initiates the sending of a message. The method C should be called for each address that the message is to be sent to. The C method can some additional ESMTP OPTIONS which is passed in hash like fashion, using key and value pairs. Possible options are: Size => Return => "FULL" | "HDRS" Bits => "7" | "8" | "binary" Transaction =>
Envelope => # xtext-encodes its argument ENVID => # similar to Envelope, but expects argument encoded XVERP => 1 AUTH => # encoded address according to RFC 2554 The C and C parameters are used for DSN (Delivery Status Notification). The submitter address in C option is expected to be in a format as required by RFC 2554, in an RFC2821-quoted form and xtext-encoded, or <> . =item reset () Reset the status of the server. This may be called after a message has been initiated, but before any data has been sent, to cancel the sending of the message. =item recipient ( ADDRESS [, ADDRESS, [...]] [, OPTIONS ] ) Notify the server that the current message should be sent to all of the addresses given. Each address is sent as a separate command to the server. Should the sending of any address result in a failure then the process is aborted and a I value is returned. It is up to the user to call C if they so desire. The C method can also pass additional case-sensitive OPTIONS as an anonymous hash using key and value pairs. Possible options are: Notify => ['NEVER'] or ['SUCCESS','FAILURE','DELAY'] (see below) ORcpt => SkipBad => 1 (to ignore bad addresses) If C is true the C will not return an error when a bad address is encountered and it will return an array of addresses that did succeed. $smtp->recipient($recipient1,$recipient2); # Good $smtp->recipient($recipient1,$recipient2, { SkipBad => 1 }); # Good $smtp->recipient($recipient1,$recipient2, { Notify => ['FAILURE','DELAY'], SkipBad => 1 }); # Good @goodrecips=$smtp->recipient(@recipients, { Notify => ['FAILURE'], SkipBad => 1 }); # Good $smtp->recipient("$recipient,$recipient2"); # BAD Notify is used to request Delivery Status Notifications (DSNs), but your SMTP/ESMTP service may not respect this request depending upon its version and your site's SMTP configuration. Leaving out the Notify option usually defaults an SMTP service to its default behavior equivalent to ['FAILURE'] notifications only, but again this may be dependent upon your site's SMTP configuration. The NEVER keyword must appear by itself if used within the Notify option and "requests that a DSN not be returned to the sender under any conditions." {Notify => ['NEVER']} $smtp->recipient(@recipients, { Notify => ['NEVER'], SkipBad => 1 }); # Good You may use any combination of these three values 'SUCCESS','FAILURE','DELAY' in the anonymous array reference as defined by RFC3461 (see http://www.ietf.org/rfc/rfc3461.txt for more information. Note: quotations in this topic from same.). A Notify parameter of 'SUCCESS' or 'FAILURE' "requests that a DSN be issued on successful delivery or delivery failure, respectively." A Notify parameter of 'DELAY' "indicates the sender's willingness to receive delayed DSNs. Delayed DSNs may be issued if delivery of a message has been delayed for an unusual amount of time (as determined by the Message Transfer Agent (MTA) at which the message is delayed), but the final delivery status (whether successful or failure) cannot be determined. The absence of the DELAY keyword in a NOTIFY parameter requests that a "delayed" DSN NOT be issued under any conditions." {Notify => ['SUCCESS','FAILURE','DELAY']} $smtp->recipient(@recipients, { Notify => ['FAILURE','DELAY'], SkipBad => 1 }); # Good ORcpt is also part of the SMTP DSN extension according to RFC3461. It is used to pass along the original recipient that the mail was first sent to. The machine that generates a DSN will use this address to inform the sender, because he can't know if recipients get rewritten by mail servers. It is expected to be in a format as required by RFC3461, xtext-encoded. =item to ( ADDRESS [, ADDRESS [...]] ) =item cc ( ADDRESS [, ADDRESS [...]] ) =item bcc ( ADDRESS [, ADDRESS [...]] ) Synonyms for C. =item data ( [ DATA ] ) Initiate the sending of the data from the current message. C may be a reference to a list or a list and must be encoded by the caller to octets of whatever encoding is required, e.g. by using the Encode module's C function. If specified the contents of C and a termination string C<".\r\n"> is sent to the server. The result will be true if the data was accepted. If C is not specified then the result will indicate that the server wishes the data to be sent. The data must then be sent using the C and C methods described in L. =item bdat ( DATA ) =item bdatlast ( DATA ) Use the alternate DATA command "BDAT" of the data chunking service extension defined in RFC1830 for efficiently sending large MIME messages. =item expand ( ADDRESS ) Request the server to expand the given address Returns an array which contains the text read from the server. =item verify ( ADDRESS ) Verify that C
is a legitimate mailing address. Most sites usually disable this feature in their SMTP service configuration. Use "Debug => 1" option under new() to see if disabled. =item help ( [ $subject ] ) Request help text from the server. Returns the text or undef upon failure =item quit () Send the QUIT command to the remote SMTP server and close the socket connection. =item can_inet6 () Returns whether we can use IPv6. =item can_ssl () Returns whether we can use SSL. =back =head1 ADDRESSES Net::SMTP attempts to DWIM with addresses that are passed. For example an application might extract The From: line from an email and pass that to mail(). While this may work, it is not recommended. The application should really use a module like L to extract the mail address and pass that. If C is passed to the constructor, then addresses should be a valid rfc2821-quoted address, although Net::SMTP will accept the address surrounded by angle brackets. funny user@domain WRONG "funny user"@domain RIGHT, recommended <"funny user"@domain> OK =head1 SEE ALSO L, L =head1 AUTHOR Graham Barr EFE. Steve Hay EFE is now maintaining libnet as of version 1.22_02. =head1 COPYRIGHT Copyright (C) 1995-2004 Graham Barr. All rights reserved. Copyright (C) 2013-2016 Steve Hay. All rights reserved. =head1 LICENCE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e. under the terms of either the GNU General Public License or the Artistic License, as specified in the F file. =cut PK f1]ť''HTTP.pmnu[package Net::HTTP; $Net::HTTP::VERSION = '6.17'; use strict; use warnings; use vars qw($SOCKET_CLASS); unless ($SOCKET_CLASS) { # Try several, in order of capability and preference if (eval { require IO::Socket::IP }) { $SOCKET_CLASS = "IO::Socket::IP"; # IPv4+IPv6 } elsif (eval { require IO::Socket::INET6 }) { $SOCKET_CLASS = "IO::Socket::INET6"; # IPv4+IPv6 } elsif (eval { require IO::Socket::INET }) { $SOCKET_CLASS = "IO::Socket::INET"; # IPv4 only } else { require IO::Socket; $SOCKET_CLASS = "IO::Socket::INET"; } } require Net::HTTP::Methods; require Carp; our @ISA = ($SOCKET_CLASS, 'Net::HTTP::Methods'); sub new { my $class = shift; Carp::croak("No Host option provided") unless @_; $class->SUPER::new(@_); } sub configure { my($self, $cnf) = @_; $self->http_configure($cnf); } sub http_connect { my($self, $cnf) = @_; $self->SUPER::configure($cnf); } 1; =pod =encoding UTF-8 =head1 NAME Net::HTTP - Low-level HTTP connection (client) =head1 VERSION version 6.17 =head1 SYNOPSIS use Net::HTTP; my $s = Net::HTTP->new(Host => "www.perl.com") || die $@; $s->write_request(GET => "/", 'User-Agent' => "Mozilla/5.0"); my($code, $mess, %h) = $s->read_response_headers; while (1) { my $buf; my $n = $s->read_entity_body($buf, 1024); die "read failed: $!" unless defined $n; last unless $n; print $buf; } =head1 DESCRIPTION The C class is a low-level HTTP client. An instance of the C class represents a connection to an HTTP server. The HTTP protocol is described in RFC 2616. The C class supports C and C. C is a sub-class of one of C (IPv6+IPv4), C (IPv6+IPv4), or C (IPv4 only). You can mix the methods described below with reading and writing from the socket directly. This is not necessary a good idea, unless you know what you are doing. The following methods are provided (in addition to those of C): =over =item $s = Net::HTTP->new( %options ) The C constructor method takes the same options as C's as well as these: Host: Initial host attribute value KeepAlive: Initial keep_alive attribute value SendTE: Initial send_te attribute_value HTTPVersion: Initial http_version attribute value PeerHTTPVersion: Initial peer_http_version attribute value MaxLineLength: Initial max_line_length attribute value MaxHeaderLines: Initial max_header_lines attribute value The C option is also the default for C's C. The C defaults to 80 if not provided. The C specification can also be embedded in the C by preceding it with a ":", and closing the IPv6 address on brackets "[]" if necessary: "192.0.2.1:80","[2001:db8::1]:80","any.example.com:80". The C option provided by C's constructor method is not allowed. If unable to connect to the given HTTP server then the constructor returns C and $@ contains the reason. After a successful connect, a C object is returned. =item $s->host Get/set the default value of the C header to send. The $host must not be set to an empty string (or C) for HTTP/1.1. =item $s->keep_alive Get/set the I value. If this value is TRUE then the request will be sent with headers indicating that the server should try to keep the connection open so that multiple requests can be sent. The actual headers set will depend on the value of the C and C attributes. =item $s->send_te Get/set the a value indicating if the request will be sent with a "TE" header to indicate the transfer encodings that the server can choose to use. The list of encodings announced as accepted by this client depends on availability of the following modules: C for I, and C for I. =item $s->http_version Get/set the HTTP version number that this client should announce. This value can only be set to "1.0" or "1.1". The default is "1.1". =item $s->peer_http_version Get/set the protocol version number of our peer. This value will initially be "1.0", but will be updated by a successful read_response_headers() method call. =item $s->max_line_length Get/set a limit on the length of response line and response header lines. The default is 8192. A value of 0 means no limit. =item $s->max_header_length Get/set a limit on the number of header lines that a response can have. The default is 128. A value of 0 means no limit. =item $s->format_request($method, $uri, %headers, [$content]) Format a request message and return it as a string. If the headers do not include a C header, then a header is inserted with the value of the C attribute. Headers like C and C might also be added depending on the status of the C attribute. If $content is given (and it is non-empty), then a C header is automatically added unless it was already present. =item $s->write_request($method, $uri, %headers, [$content]) Format and send a request message. Arguments are the same as for format_request(). Returns true if successful. =item $s->format_chunk( $data ) Returns the string to be written for the given chunk of data. =item $s->write_chunk($data) Will write a new chunk of request entity body data. This method should only be used if the C header with a value of C was sent in the request. Note, writing zero-length data is a no-op. Use the write_chunk_eof() method to signal end of entity body data. Returns true if successful. =item $s->format_chunk_eof( %trailers ) Returns the string to be written for signaling EOF when a C of C is used. =item $s->write_chunk_eof( %trailers ) Will write eof marker for chunked data and optional trailers. Note that trailers should not really be used unless is was signaled with a C header. Returns true if successful. =item ($code, $mess, %headers) = $s->read_response_headers( %opts ) Read response headers from server and return it. The $code is the 3 digit HTTP status code (see L) and $mess is the textual message that came with it. Headers are then returned as key/value pairs. Since key letter casing is not normalized and the same key can even occur multiple times, assigning these values directly to a hash is not wise. Only the $code is returned if this method is called in scalar context. As a side effect this method updates the 'peer_http_version' attribute. Options might be passed in as key/value pairs. There are currently only two options supported; C and C. The C option will make read_response_headers() more forgiving towards servers that have not learned how to speak HTTP properly. The C option is a boolean flag, and is enabled by passing in a TRUE value. The C option can be used to capture bad header lines when C is enabled. The value should be an array reference. Bad header lines will be pushed onto the array. The C option must be specified in order to communicate with pre-HTTP/1.0 servers that don't describe the response outcome or the data they send back with a header block. For these servers peer_http_version is set to "0.9" and this method returns (200, "Assumed OK"). The method will raise an exception (die) if the server does not speak proper HTTP or if the C or C limits are reached. If the C option is turned on and C and C checks are turned off, then no exception will be raised and this method will always return a response code. =item $n = $s->read_entity_body($buf, $size); Reads chunks of the entity body content. Basically the same interface as for read() and sysread(), but the buffer offset argument is not supported yet. This method should only be called after a successful read_response_headers() call. The return value will be C on read errors, 0 on EOF, -1 if no data could be returned this time, otherwise the number of bytes assigned to $buf. The $buf is set to "" when the return value is -1. You normally want to retry this call if this function returns either -1 or C with C<$!> as EINTR or EAGAIN (see L). EINTR can happen if the application catches signals and EAGAIN can happen if you made the socket non-blocking. This method will raise exceptions (die) if the server does not speak proper HTTP. This can only happen when reading chunked data. =item %headers = $s->get_trailers After read_entity_body() has returned 0 to indicate end of the entity body, you might call this method to pick up any trailers. =item $s->_rbuf Get/set the read buffer content. The read_response_headers() and read_entity_body() methods use an internal buffer which they will look for data before they actually sysread more from the socket itself. If they read too much, the remaining data will be left in this buffer. =item $s->_rbuf_length Returns the number of bytes in the read buffer. This should always be the same as: length($s->_rbuf) but might be more efficient. =back =head1 SUBCLASSING The read_response_headers() and read_entity_body() will invoke the sysread() method when they need more data. Subclasses might want to override this method to control how reading takes place. The object itself is a glob. Subclasses should avoid using hash key names prefixed with C and C. =head1 SEE ALSO L, L, L =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001-2017 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # ABSTRACT: Low-level HTTP connection (client) PK f1]IH{{FTP/I.pmnu[## ## Package to read/write on BINARY data connections ## package Net::FTP::I; use 5.008001; use strict; use warnings; use Carp; use Net::FTP::dataconn; our @ISA = qw(Net::FTP::dataconn); our $VERSION = "3.11"; our $buf; sub read { my $data = shift; local *buf = \$_[0]; shift; my $size = shift || croak 'read($buf,$size,[$timeout])'; my $timeout = @_ ? shift: $data->timeout; my $n; if ($size > length ${*$data} and !${*$data}{'net_ftp_eof'}) { $data->can_read($timeout) or croak "Timeout"; my $blksize = ${*$data}{'net_ftp_blksize'}; $blksize = $size if $size > $blksize; unless ($n = sysread($data, ${*$data}, $blksize, length ${*$data})) { return unless defined $n; ${*$data}{'net_ftp_eof'} = 1; } } $buf = substr(${*$data}, 0, $size); $n = length($buf); substr(${*$data}, 0, $n) = ''; ${*$data}{'net_ftp_bytesread'} += $n; $n; } sub write { my $data = shift; local *buf = \$_[0]; shift; my $size = shift || croak 'write($buf,$size,[$timeout])'; my $timeout = @_ ? shift: $data->timeout; # If the remote server has closed the connection we will be signal'd # when we write. This can happen if the disk on the remote server fills up local $SIG{PIPE} = 'IGNORE' unless ($SIG{PIPE} || '') eq 'IGNORE' or $^O eq 'MacOS'; my $sent = $size; my $off = 0; my $blksize = ${*$data}{'net_ftp_blksize'}; while ($sent > 0) { $data->can_write($timeout) or croak "Timeout"; my $n = syswrite($data, $buf, $sent > $blksize ? $blksize : $sent, $off); return unless defined($n); $sent -= $n; $off += $n; } $size; } 1; PK f1]B FTP/dataconn.pmnu[## ## Generic data connection package ## package Net::FTP::dataconn; use 5.008001; use strict; use warnings; use Carp; use Errno; use Net::Cmd; our $VERSION = '3.11'; $Net::FTP::IOCLASS or die "please load Net::FTP before Net::FTP::dataconn"; our @ISA = $Net::FTP::IOCLASS; sub reading { my $data = shift; ${*$data}{'net_ftp_bytesread'} = 0; } sub abort { my $data = shift; my $ftp = ${*$data}{'net_ftp_cmd'}; # no need to abort if we have finished the xfer return $data->close if ${*$data}{'net_ftp_eof'}; # for some reason if we continuously open RETR connections and not # read a single byte, then abort them after a while the server will # close our connection, this prevents the unexpected EOF on the # command channel -- GMB if (exists ${*$data}{'net_ftp_bytesread'} && (${*$data}{'net_ftp_bytesread'} == 0)) { my $buf = ""; my $timeout = $data->timeout; $data->can_read($timeout) && sysread($data, $buf, 1); } ${*$data}{'net_ftp_eof'} = 1; # fake $ftp->abort; # this will close me } sub _close { my $data = shift; my $ftp = ${*$data}{'net_ftp_cmd'}; $data->SUPER::close(); delete ${*$ftp}{'net_ftp_dataconn'} if defined $ftp && exists ${*$ftp}{'net_ftp_dataconn'} && $data == ${*$ftp}{'net_ftp_dataconn'}; } sub close { my $data = shift; my $ftp = ${*$data}{'net_ftp_cmd'}; if (exists ${*$data}{'net_ftp_bytesread'} && !${*$data}{'net_ftp_eof'}) { my $junk; eval { local($SIG{__DIE__}); $data->read($junk, 1, 0) }; return $data->abort unless ${*$data}{'net_ftp_eof'}; } $data->_close; return unless defined $ftp; $ftp->response() == CMD_OK && $ftp->message =~ /unique file name:\s*(\S*)\s*\)/ && (${*$ftp}{'net_ftp_unique'} = $1); $ftp->status == CMD_OK; } sub _select { my ($data, $timeout, $do_read) = @_; my ($rin, $rout, $win, $wout, $tout, $nfound); vec($rin = '', fileno($data), 1) = 1; ($win, $rin) = ($rin, $win) unless $do_read; while (1) { $nfound = select($rout = $rin, $wout = $win, undef, $tout = $timeout); last if $nfound >= 0; croak "select: $!" unless $!{EINTR}; } $nfound; } sub can_read { _select(@_[0, 1], 1); } sub can_write { _select(@_[0, 1], 0); } sub cmd { my $ftp = shift; ${*$ftp}{'net_ftp_cmd'}; } sub bytes_read { my $ftp = shift; ${*$ftp}{'net_ftp_bytesread'} || 0; } 1; __END__ =head1 NAME Net::FTP::dataconn - FTP Client data connection class =head1 DESCRIPTION Some of the methods defined in C return an object which will be derived from this class. The dataconn class itself is derived from the C class, so any normal IO operations can be performed. However the following methods are defined in the dataconn class and IO should be performed using these. =over 4 =item read ( BUFFER, SIZE [, TIMEOUT ] ) Read C bytes of data from the server and place it into C, also performing any translation necessary. C is optional, if not given, the timeout value from the command connection will be used. Returns the number of bytes read before any translation. =item write ( BUFFER, SIZE [, TIMEOUT ] ) Write C bytes of data from C to the server, also performing any translation necessary. C is optional, if not given, the timeout value from the command connection will be used. Returns the number of bytes written before any translation. =item bytes_read () Returns the number of bytes read so far. =item abort () Abort the current data transfer. =item close () Close the data connection and get a response from the FTP server. Returns I if the connection was closed successfully and the first digit of the response from the server was a '2'. =back =cut PK f1]c;FTP/E.pmnu[package Net::FTP::E; use 5.008001; use strict; use warnings; use Net::FTP::I; our @ISA = qw(Net::FTP::I); our $VERSION = "3.11"; 1; PK f1]8` ` FTP/A.pmnu[## ## Package to read/write on ASCII data connections ## package Net::FTP::A; use 5.008001; use strict; use warnings; use Carp; use Net::FTP::dataconn; our @ISA = qw(Net::FTP::dataconn); our $VERSION = "3.11"; our $buf; sub read { my $data = shift; local *buf = \$_[0]; shift; my $size = shift || croak 'read($buf,$size,[$offset])'; my $timeout = @_ ? shift: $data->timeout; if (length(${*$data}) < $size && !${*$data}{'net_ftp_eof'}) { my $blksize = ${*$data}{'net_ftp_blksize'}; $blksize = $size if $size > $blksize; my $l = 0; my $n; READ: { my $readbuf = defined(${*$data}{'net_ftp_cr'}) ? "\015" : ''; $data->can_read($timeout) or croak "Timeout"; if ($n = sysread($data, $readbuf, $blksize, length $readbuf)) { ${*$data}{'net_ftp_bytesread'} += $n; ${*$data}{'net_ftp_cr'} = substr($readbuf, -1) eq "\015" ? chop($readbuf) : undef; } else { return unless defined $n; ${*$data}{'net_ftp_eof'} = 1; } $readbuf =~ s/\015\012/\n/sgo; ${*$data} .= $readbuf; unless (length(${*$data})) { redo READ if ($n > 0); $size = length(${*$data}) if ($n == 0); } } } $buf = substr(${*$data}, 0, $size); substr(${*$data}, 0, $size) = ''; length $buf; } sub write { my $data = shift; local *buf = \$_[0]; shift; my $size = shift || croak 'write($buf,$size,[$timeout])'; my $timeout = @_ ? shift: $data->timeout; my $nr = (my $tmp = substr($buf, 0, $size)) =~ tr/\r\n/\015\012/; $tmp =~ s/(?can_write($timeout) or croak "Timeout"; $off += $wrote; $wrote = syswrite($data, substr($tmp, $off), $len > $blksize ? $blksize : $len); return unless defined($wrote); $len -= $wrote; } $size; } 1; PK f1]|IFTP/L.pmnu[package Net::FTP::L; use 5.008001; use strict; use warnings; use Net::FTP::I; our @ISA = qw(Net::FTP::I); our $VERSION = "3.11"; 1; PK f1] * libnetFAQ.podnu[=encoding utf-8 The L. You can access the original document on L. PK f1]6Time.pmnu[# Net::Time.pm # # Copyright (C) 1995-2004 Graham Barr. All rights reserved. # Copyright (C) 2014 Steve Hay. All rights reserved. # This module is free software; you can redistribute it and/or modify it under # the same terms as Perl itself, i.e. under the terms of either the GNU General # Public License or the Artistic License, as specified in the F file. package Net::Time; use 5.008001; use strict; use warnings; use Carp; use Exporter; use IO::Select; use IO::Socket; use Net::Config; our @ISA = qw(Exporter); our @EXPORT_OK = qw(inet_time inet_daytime); our $VERSION = "3.11"; our $TIMEOUT = 120; sub _socket { my ($pname, $pnum, $host, $proto, $timeout) = @_; $proto ||= 'udp'; my $port = (getservbyname($pname, $proto))[2] || $pnum; my $hosts = defined $host ? [$host] : $NetConfig{$pname . '_hosts'}; my $me; foreach my $addr (@$hosts) { $me = IO::Socket::INET->new( PeerAddr => $addr, PeerPort => $port, Proto => $proto ) and last; } return unless $me; $me->send("\n") if $proto eq 'udp'; $timeout = $TIMEOUT unless defined $timeout; IO::Select->new($me)->can_read($timeout) ? $me : undef; } sub inet_time { my $s = _socket('time', 37, @_) || return; my $buf = ''; my $offset = 0 | 0; return unless defined $s->recv($buf, length(pack("N", 0))); # unpack, we | 0 to ensure we have an unsigned my $time = (unpack("N", $buf))[0] | 0; # the time protocol return time in seconds since 1900, convert # it to a the required format if ($^O eq "MacOS") { # MacOS return seconds since 1904, 1900 was not a leap year. $offset = (4 * 31536000) | 0; } else { # otherwise return seconds since 1972, there were 17 leap years between # 1900 and 1972 $offset = (70 * 31536000 + 17 * 86400) | 0; } $time - $offset; } sub inet_daytime { my $s = _socket('daytime', 13, @_) || return; my $buf = ''; defined($s->recv($buf, 1024)) ? $buf : undef; } 1; __END__ =head1 NAME Net::Time - time and daytime network client interface =head1 SYNOPSIS use Net::Time qw(inet_time inet_daytime); print inet_time(); # use default host from Net::Config print inet_time('localhost'); print inet_time('localhost', 'tcp'); print inet_daytime(); # use default host from Net::Config print inet_daytime('localhost'); print inet_daytime('localhost', 'tcp'); =head1 DESCRIPTION C provides subroutines that obtain the time on a remote machine. =over 4 =item inet_time ( [HOST [, PROTOCOL [, TIMEOUT]]]) Obtain the time on C, or some default host if C is not given or not defined, using the protocol as defined in RFC868. The optional argument C should define the protocol to use, either C or C. The result will be a time value in the same units as returned by time() or I upon failure. =item inet_daytime ( [HOST [, PROTOCOL [, TIMEOUT]]]) Obtain the time on C, or some default host if C is not given or not defined, using the protocol as defined in RFC867. The optional argument C should define the protocol to use, either C or C. The result will be an ASCII string or I upon failure. =back =head1 AUTHOR Graham Barr EFE. Steve Hay EFE is now maintaining libnet as of version 1.22_02. =head1 COPYRIGHT Copyright (C) 1995-2004 Graham Barr. All rights reserved. Copyright (C) 2014 Steve Hay. All rights reserved. =head1 LICENCE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e. under the terms of either the GNU General Public License or the Artistic License, as specified in the F file. =cut PK f1]ZFTP.pmnu[# Net::FTP.pm # # Copyright (C) 1995-2004 Graham Barr. All rights reserved. # Copyright (C) 2013-2017 Steve Hay. All rights reserved. # This module is free software; you can redistribute it and/or modify it under # the same terms as Perl itself, i.e. under the terms of either the GNU General # Public License or the Artistic License, as specified in the F file. # # Documentation (at end) improved 1996 by Nathan Torkington . package Net::FTP; use 5.008001; use strict; use warnings; use Carp; use Fcntl qw(O_WRONLY O_RDONLY O_APPEND O_CREAT O_TRUNC); use IO::Socket; use Net::Cmd; use Net::Config; use Socket; use Time::Local; our $VERSION = '3.11'; our $IOCLASS; my $family_key; BEGIN { # Code for detecting if we can use SSL my $ssl_class = eval { require IO::Socket::SSL; # first version with default CA on most platforms no warnings 'numeric'; IO::Socket::SSL->VERSION(2.007); } && 'IO::Socket::SSL'; my $nossl_warn = !$ssl_class && 'To use SSL please install IO::Socket::SSL with version>=2.007'; # Code for detecting if we can use IPv6 my $inet6_class = eval { require IO::Socket::IP; no warnings 'numeric'; IO::Socket::IP->VERSION(0.25); } && 'IO::Socket::IP' || eval { require IO::Socket::INET6; no warnings 'numeric'; IO::Socket::INET6->VERSION(2.62); } && 'IO::Socket::INET6'; sub can_ssl { $ssl_class }; sub can_inet6 { $inet6_class }; $IOCLASS = $ssl_class || $inet6_class || 'IO::Socket::INET'; $family_key = ( $ssl_class ? $ssl_class->can_ipv6 : $inet6_class || '' ) eq 'IO::Socket::IP' ? 'Family' : 'Domain'; } our @ISA = ('Exporter','Net::Cmd',$IOCLASS); use constant TELNET_IAC => 255; use constant TELNET_IP => 244; use constant TELNET_DM => 242; use constant EBCDIC => $^O eq 'os390'; sub new { my $pkg = shift; my ($peer, %arg); if (@_ % 2) { $peer = shift; %arg = @_; } else { %arg = @_; $peer = delete $arg{Host}; } my $host = $peer; my $fire = undef; my $fire_type = undef; if (exists($arg{Firewall}) || Net::Config->requires_firewall($peer)) { $fire = $arg{Firewall} || $ENV{FTP_FIREWALL} || $NetConfig{ftp_firewall} || undef; if (defined $fire) { $peer = $fire; delete $arg{Port}; $fire_type = $arg{FirewallType} || $ENV{FTP_FIREWALL_TYPE} || $NetConfig{firewall_type} || undef; } } my %tlsargs; if (can_ssl()) { # for name verification strip port from domain:port, ipv4:port, [ipv6]:port (my $hostname = $host) =~s{(? 'ftp', SSL_verifycn_name => $hostname, # use SNI if supported by IO::Socket::SSL $pkg->can_client_sni ? (SSL_hostname => $hostname):(), # reuse SSL session of control connection in data connections SSL_session_cache => Net::FTP::_SSL_SingleSessionCache->new, ); # user defined SSL arg $tlsargs{$_} = $arg{$_} for(grep { m{^SSL_} } keys %arg); } elsif ($arg{SSL}) { croak("IO::Socket::SSL >= 2.007 needed for SSL support"); } my $ftp = $pkg->SUPER::new( PeerAddr => $peer, PeerPort => $arg{Port} || ($arg{SSL} ? 'ftps(990)' : 'ftp(21)'), LocalAddr => $arg{'LocalAddr'}, $family_key => $arg{Domain} || $arg{Family}, Proto => 'tcp', Timeout => defined $arg{Timeout} ? $arg{Timeout} : 120, %tlsargs, $arg{SSL} ? ():( SSL_startHandshake => 0 ), ) or return; ${*$ftp}{'net_ftp_host'} = $host; # Remote hostname ${*$ftp}{'net_ftp_type'} = 'A'; # ASCII/binary/etc mode ${*$ftp}{'net_ftp_blksize'} = abs($arg{'BlockSize'} || 10240); ${*$ftp}{'net_ftp_localaddr'} = $arg{'LocalAddr'}; ${*$ftp}{'net_ftp_domain'} = $arg{Domain} || $arg{Family}; ${*$ftp}{'net_ftp_firewall'} = $fire if (defined $fire); ${*$ftp}{'net_ftp_firewall_type'} = $fire_type if (defined $fire_type); ${*$ftp}{'net_ftp_passive'} = int exists $arg{Passive} ? $arg{Passive} : exists $ENV{FTP_PASSIVE} ? $ENV{FTP_PASSIVE} : defined $fire ? $NetConfig{ftp_ext_passive} : $NetConfig{ftp_int_passive}; # Whew! :-) ${*$ftp}{net_ftp_tlsargs} = \%tlsargs if %tlsargs; if ($arg{SSL}) { ${*$ftp}{net_ftp_tlsprot} = 'P'; ${*$ftp}{net_ftp_tlsdirect} = 1; } $ftp->hash(exists $arg{Hash} ? $arg{Hash} : 0, 1024); $ftp->autoflush(1); $ftp->debug(exists $arg{Debug} ? $arg{Debug} : undef); unless ($ftp->response() == CMD_OK) { $ftp->close(); # keep @$ if no message. Happens, when response did not start with a code. $@ = $ftp->message || $@; undef $ftp; } $ftp; } ## ## User interface methods ## sub host { my $me = shift; ${*$me}{'net_ftp_host'}; } sub passive { my $ftp = shift; return ${*$ftp}{'net_ftp_passive'} unless @_; ${*$ftp}{'net_ftp_passive'} = shift; } sub hash { my $ftp = shift; # self my ($h, $b) = @_; unless ($h) { delete ${*$ftp}{'net_ftp_hash'}; return [\*STDERR, 0]; } ($h, $b) = (ref($h) ? $h : \*STDERR, $b || 1024); select((select($h), $| = 1)[0]); $b = 512 if $b < 512; ${*$ftp}{'net_ftp_hash'} = [$h, $b]; } sub quit { my $ftp = shift; $ftp->_QUIT; $ftp->close; } sub DESTROY { } sub ascii { shift->type('A', @_); } sub binary { shift->type('I', @_); } sub ebcdic { carp "TYPE E is unsupported, shall default to I"; shift->type('E', @_); } sub byte { carp "TYPE L is unsupported, shall default to I"; shift->type('L', @_); } # Allow the user to send a command directly, BE CAREFUL !! sub quot { my $ftp = shift; my $cmd = shift; $ftp->command(uc $cmd, @_); $ftp->response(); } sub site { my $ftp = shift; $ftp->command("SITE", @_); $ftp->response(); } sub mdtm { my $ftp = shift; my $file = shift; # Server Y2K bug workaround # # sigh; some idiotic FTP servers use ("19%d",tm.tm_year) instead of # ("%d",tm.tm_year+1900). This results in an extra digit in the # string returned. To account for this we allow an optional extra # digit in the year. Then if the first two digits are 19 we use the # remainder, otherwise we subtract 1900 from the whole year. $ftp->_MDTM($file) && $ftp->message =~ /((\d\d)(\d\d\d?))(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ ? timegm($8, $7, $6, $5, $4 - 1, $2 eq '19' ? $3 : ($1 - 1900)) : undef; } sub size { my $ftp = shift; my $file = shift; my $io; if ($ftp->supported("SIZE")) { return $ftp->_SIZE($file) ? ($ftp->message =~ /(\d+)\s*(bytes?\s*)?$/)[0] : undef; } elsif ($ftp->supported("STAT")) { my @msg; return unless $ftp->_STAT($file) && (@msg = $ftp->message) == 3; foreach my $line (@msg) { return (split(/\s+/, $line))[4] if $line =~ /^[-rwxSsTt]{10}/; } } else { my @files = $ftp->dir($file); if (@files) { return (split(/\s+/, $1))[4] if $files[0] =~ /^([-rwxSsTt]{10}.*)$/; } } undef; } sub starttls { my $ftp = shift; can_ssl() or croak("IO::Socket::SSL >= 2.007 needed for SSL support"); $ftp->is_SSL and croak("called starttls within SSL session"); $ftp->_AUTH('TLS') == CMD_OK or return; $ftp->connect_SSL or return; $ftp->prot('P'); return 1; } sub prot { my ($ftp,$prot) = @_; $prot eq 'C' or $prot eq 'P' or croak("prot must by C or P"); $ftp->_PBSZ(0) or return; $ftp->_PROT($prot) or return; ${*$ftp}{net_ftp_tlsprot} = $prot; return 1; } sub stoptls { my $ftp = shift; $ftp->is_SSL or croak("called stoptls outside SSL session"); ${*$ftp}{net_ftp_tlsdirect} and croak("cannot stoptls direct SSL session"); $ftp->_CCC() or return; $ftp->stop_SSL(); return 1; } sub login { my ($ftp, $user, $pass, $acct) = @_; my ($ok, $ruser, $fwtype); unless (defined $user) { require Net::Netrc; my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_host'}); ($user, $pass, $acct) = $rc->lpa() if ($rc); } $user ||= "anonymous"; $ruser = $user; $fwtype = ${*$ftp}{'net_ftp_firewall_type'} || $NetConfig{'ftp_firewall_type'} || 0; if ($fwtype && defined ${*$ftp}{'net_ftp_firewall'}) { if ($fwtype == 1 || $fwtype == 7) { $user .= '@' . ${*$ftp}{'net_ftp_host'}; } else { require Net::Netrc; my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}); my ($fwuser, $fwpass, $fwacct) = $rc ? $rc->lpa() : (); if ($fwtype == 5) { $user = join('@', $user, $fwuser, ${*$ftp}{'net_ftp_host'}); $pass = $pass . '@' . $fwpass; } else { if ($fwtype == 2) { $user .= '@' . ${*$ftp}{'net_ftp_host'}; } elsif ($fwtype == 6) { $fwuser .= '@' . ${*$ftp}{'net_ftp_host'}; } $ok = $ftp->_USER($fwuser); return 0 unless $ok == CMD_OK || $ok == CMD_MORE; $ok = $ftp->_PASS($fwpass || ""); return 0 unless $ok == CMD_OK || $ok == CMD_MORE; $ok = $ftp->_ACCT($fwacct) if defined($fwacct); if ($fwtype == 3) { $ok = $ftp->command("SITE", ${*$ftp}{'net_ftp_host'})->response; } elsif ($fwtype == 4) { $ok = $ftp->command("OPEN", ${*$ftp}{'net_ftp_host'})->response; } return 0 unless $ok == CMD_OK || $ok == CMD_MORE; } } } $ok = $ftp->_USER($user); # Some dumb firewalls don't prefix the connection messages $ok = $ftp->response() if ($ok == CMD_OK && $ftp->code == 220 && $user =~ /\@/); if ($ok == CMD_MORE) { unless (defined $pass) { require Net::Netrc; my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_host'}, $ruser); ($ruser, $pass, $acct) = $rc->lpa() if ($rc); $pass = '-anonymous@' if (!defined $pass && (!defined($ruser) || $ruser =~ /^anonymous/o)); } $ok = $ftp->_PASS($pass || ""); } $ok = $ftp->_ACCT($acct) if (defined($acct) && ($ok == CMD_MORE || $ok == CMD_OK)); if ($fwtype == 7 && $ok == CMD_OK && defined ${*$ftp}{'net_ftp_firewall'}) { my ($f, $auth, $resp) = _auth_id($ftp); $ftp->authorize($auth, $resp) if defined($resp); } $ok == CMD_OK; } sub account { @_ == 2 or croak 'usage: $ftp->account( ACCT )'; my $ftp = shift; my $acct = shift; $ftp->_ACCT($acct) == CMD_OK; } sub _auth_id { my ($ftp, $auth, $resp) = @_; unless (defined $resp) { require Net::Netrc; $auth ||= eval { (getpwuid($>))[0] } || $ENV{NAME}; my $rc = Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}, $auth) || Net::Netrc->lookup(${*$ftp}{'net_ftp_firewall'}); ($auth, $resp) = $rc->lpa() if ($rc); } ($ftp, $auth, $resp); } sub authorize { @_ >= 1 || @_ <= 3 or croak 'usage: $ftp->authorize( [AUTH [, RESP]])'; my ($ftp, $auth, $resp) = &_auth_id; my $ok = $ftp->_AUTH($auth || ""); return $ftp->_RESP($resp || "") if ($ok == CMD_MORE); $ok == CMD_OK; } sub rename { @_ == 3 or croak 'usage: $ftp->rename(FROM, TO)'; my ($ftp, $from, $to) = @_; $ftp->_RNFR($from) && $ftp->_RNTO($to); } sub type { my $ftp = shift; my $type = shift; my $oldval = ${*$ftp}{'net_ftp_type'}; return $oldval unless (defined $type); return unless ($ftp->_TYPE($type, @_)); ${*$ftp}{'net_ftp_type'} = join(" ", $type, @_); $oldval; } sub alloc { my $ftp = shift; my $size = shift; my $oldval = ${*$ftp}{'net_ftp_allo'}; return $oldval unless (defined $size); return unless ($ftp->supported("ALLO") and $ftp->_ALLO($size, @_)); ${*$ftp}{'net_ftp_allo'} = join(" ", $size, @_); $oldval; } sub abort { my $ftp = shift; send($ftp, pack("CCC", TELNET_IAC, TELNET_IP, TELNET_IAC), MSG_OOB); $ftp->command(pack("C", TELNET_DM) . "ABOR"); ${*$ftp}{'net_ftp_dataconn'}->close() if defined ${*$ftp}{'net_ftp_dataconn'}; $ftp->response(); $ftp->status == CMD_OK; } sub get { my ($ftp, $remote, $local, $where) = @_; my ($loc, $len, $buf, $resp, $data); local *FD; my $localfd = ref($local) || ref(\$local) eq "GLOB"; ($local = $remote) =~ s#^.*/## unless (defined $local); croak("Bad remote filename '$remote'\n") if $remote =~ /[\r\n]/s; ${*$ftp}{'net_ftp_rest'} = $where if defined $where; my $rest = ${*$ftp}{'net_ftp_rest'}; delete ${*$ftp}{'net_ftp_port'}; delete ${*$ftp}{'net_ftp_pasv'}; $data = $ftp->retr($remote) or return; if ($localfd) { $loc = $local; } else { $loc = \*FD; unless (sysopen($loc, $local, O_CREAT | O_WRONLY | ($rest ? O_APPEND: O_TRUNC))) { carp "Cannot open Local file $local: $!\n"; $data->abort; return; } } if ($ftp->type eq 'I' && !binmode($loc)) { carp "Cannot binmode Local file $local: $!\n"; $data->abort; close($loc) unless $localfd; return; } $buf = ''; my ($count, $hashh, $hashb, $ref) = (0); ($hashh, $hashb) = @$ref if ($ref = ${*$ftp}{'net_ftp_hash'}); my $blksize = ${*$ftp}{'net_ftp_blksize'}; local $\; # Just in case while (1) { last unless $len = $data->read($buf, $blksize); if (EBCDIC && $ftp->type ne 'I') { $buf = $ftp->toebcdic($buf); $len = length($buf); } if ($hashh) { $count += $len; print $hashh "#" x (int($count / $hashb)); $count %= $hashb; } unless (print $loc $buf) { carp "Cannot write to Local file $local: $!\n"; $data->abort; close($loc) unless $localfd; return; } } print $hashh "\n" if $hashh; unless ($localfd) { unless (close($loc)) { carp "Cannot close file $local (perhaps disk space) $!\n"; return; } } unless ($data->close()) # implied $ftp->response { carp "Unable to close datastream"; return; } return $local; } sub cwd { @_ == 1 || @_ == 2 or croak 'usage: $ftp->cwd( [ DIR ] )'; my ($ftp, $dir) = @_; $dir = "/" unless defined($dir) && $dir =~ /\S/; $dir eq ".." ? $ftp->_CDUP() : $ftp->_CWD($dir); } sub cdup { @_ == 1 or croak 'usage: $ftp->cdup()'; $_[0]->_CDUP; } sub pwd { @_ == 1 || croak 'usage: $ftp->pwd()'; my $ftp = shift; $ftp->_PWD(); $ftp->_extract_path; } # rmdir( $ftp, $dir, [ $recurse ] ) # # Removes $dir on remote host via FTP. # $ftp is handle for remote host # # If $recurse is TRUE, the directory and deleted recursively. # This means all of its contents and subdirectories. # # Initial version contributed by Dinkum Software # sub rmdir { @_ == 2 || @_ == 3 or croak('usage: $ftp->rmdir( DIR [, RECURSE ] )'); # Pick off the args my ($ftp, $dir, $recurse) = @_; my $ok; return $ok if $ok = $ftp->_RMD($dir) or !$recurse; # Try to delete the contents # Get a list of all the files in the directory, excluding the current and parent directories my @filelist = map { /^(?:\S+;)+ (.+)$/ ? ($1) : () } grep { !/^(?:\S+;)*type=[cp]dir;/i } $ftp->_list_cmd("MLSD", $dir); # Fallback to using the less well-defined NLST command if MLSD fails @filelist = grep { !/^\.{1,2}$/ } $ftp->ls($dir) unless @filelist; return unless @filelist; # failed, it is probably not a directory return $ftp->delete($dir) if @filelist == 1 and $dir eq $filelist[0]; # Go thru and delete each file or the directory foreach my $file (map { m,/, ? $_ : "$dir/$_" } @filelist) { next # successfully deleted the file if $ftp->delete($file); # Failed to delete it, assume its a directory # Recurse and ignore errors, the final rmdir() will # fail on any errors here return $ok unless $ok = $ftp->rmdir($file, 1); } # Directory should be empty # Try to remove the directory again # Pass results directly to caller # If any of the prior deletes failed, this # rmdir() will fail because directory is not empty return $ftp->_RMD($dir); } sub restart { @_ == 2 || croak 'usage: $ftp->restart( BYTE_OFFSET )'; my ($ftp, $where) = @_; ${*$ftp}{'net_ftp_rest'} = $where; return; } sub mkdir { @_ == 2 || @_ == 3 or croak 'usage: $ftp->mkdir( DIR [, RECURSE ] )'; my ($ftp, $dir, $recurse) = @_; $ftp->_MKD($dir) || $recurse or return; my $path = $dir; unless ($ftp->ok) { my @path = split(m#(?=/+)#, $dir); $path = ""; while (@path) { $path .= shift @path; $ftp->_MKD($path); $path = $ftp->_extract_path($path); } # If the creation of the last element was not successful, see if we # can cd to it, if so then return path unless ($ftp->ok) { my ($status, $message) = ($ftp->status, $ftp->message); my $pwd = $ftp->pwd; if ($pwd && $ftp->cwd($dir)) { $path = $dir; $ftp->cwd($pwd); } else { undef $path; } $ftp->set_status($status, $message); } } $path; } sub delete { @_ == 2 || croak 'usage: $ftp->delete( FILENAME )'; $_[0]->_DELE($_[1]); } sub put { shift->_store_cmd("stor", @_) } sub put_unique { shift->_store_cmd("stou", @_) } sub append { shift->_store_cmd("appe", @_) } sub nlst { shift->_data_cmd("NLST", @_) } sub list { shift->_data_cmd("LIST", @_) } sub retr { shift->_data_cmd("RETR", @_) } sub stor { shift->_data_cmd("STOR", @_) } sub stou { shift->_data_cmd("STOU", @_) } sub appe { shift->_data_cmd("APPE", @_) } sub _store_cmd { my ($ftp, $cmd, $local, $remote) = @_; my ($loc, $sock, $len, $buf); local *FD; my $localfd = ref($local) || ref(\$local) eq "GLOB"; if (!defined($remote) and 'STOU' ne uc($cmd)) { croak 'Must specify remote filename with stream input' if $localfd; require File::Basename; $remote = File::Basename::basename($local); } if (defined ${*$ftp}{'net_ftp_allo'}) { delete ${*$ftp}{'net_ftp_allo'}; } else { # if the user hasn't already invoked the alloc method since the last # _store_cmd call, figure out if the local file is a regular file(not # a pipe, or device) and if so get the file size from stat, and send # an ALLO command before sending the STOR, STOU, or APPE command. my $size = do { local $^W; -f $local && -s _ }; # no ALLO if sending data from a pipe ${*$ftp}{'net_ftp_allo'} = $size if $size; } croak("Bad remote filename '$remote'\n") if defined($remote) and $remote =~ /[\r\n]/s; if ($localfd) { $loc = $local; } else { $loc = \*FD; unless (sysopen($loc, $local, O_RDONLY)) { carp "Cannot open Local file $local: $!\n"; return; } } if ($ftp->type eq 'I' && !binmode($loc)) { carp "Cannot binmode Local file $local: $!\n"; return; } delete ${*$ftp}{'net_ftp_port'}; delete ${*$ftp}{'net_ftp_pasv'}; $sock = $ftp->_data_cmd($cmd, grep { defined } $remote) or return; $remote = ($ftp->message =~ /\w+\s*:\s*(.*)/)[0] if 'STOU' eq uc $cmd; my $blksize = ${*$ftp}{'net_ftp_blksize'}; my ($count, $hashh, $hashb, $ref) = (0); ($hashh, $hashb) = @$ref if ($ref = ${*$ftp}{'net_ftp_hash'}); while (1) { last unless $len = read($loc, $buf = "", $blksize); if (EBCDIC && $ftp->type ne 'I') { $buf = $ftp->toascii($buf); $len = length($buf); } if ($hashh) { $count += $len; print $hashh "#" x (int($count / $hashb)); $count %= $hashb; } my $wlen; unless (defined($wlen = $sock->write($buf, $len)) && $wlen == $len) { $sock->abort; close($loc) unless $localfd; print $hashh "\n" if $hashh; return; } } print $hashh "\n" if $hashh; close($loc) unless $localfd; $sock->close() or return; if ('STOU' eq uc $cmd and $ftp->message =~ m/unique\s+file\s*name\s*:\s*(.*)\)|"(.*)"/) { require File::Basename; $remote = File::Basename::basename($+); } return $remote; } sub port { @_ == 1 || @_ == 2 or croak 'usage: $self->port([PORT])'; return _eprt('PORT',@_); } sub eprt { @_ == 1 || @_ == 2 or croak 'usage: $self->eprt([PORT])'; return _eprt('EPRT',@_); } sub _eprt { my ($cmd,$ftp,$port) = @_; delete ${*$ftp}{net_ftp_intern_port}; unless ($port) { my $listen = ${*$ftp}{net_ftp_listen} ||= $IOCLASS->new( Listen => 1, Timeout => $ftp->timeout, LocalAddr => $ftp->sockhost, $family_key => $ftp->sockdomain, can_ssl() ? ( %{ ${*$ftp}{net_ftp_tlsargs} }, SSL_startHandshake => 0, ):(), ); ${*$ftp}{net_ftp_intern_port} = 1; my $fam = ($listen->sockdomain == AF_INET) ? 1:2; if ( $cmd eq 'EPRT' || $fam == 2 ) { $port = "|$fam|".$listen->sockhost."|".$listen->sockport."|"; $cmd = 'EPRT'; } else { my $p = $listen->sockport; $port = join(',',split(m{\.},$listen->sockhost),$p >> 8,$p & 0xff); } } elsif (ref($port) eq 'ARRAY') { $port = join(',',split(m{\.},@$port[0]),@$port[1] >> 8,@$port[1] & 0xff); } my $ok = $cmd eq 'EPRT' ? $ftp->_EPRT($port) : $ftp->_PORT($port); ${*$ftp}{net_ftp_port} = $port if $ok; return $ok; } sub ls { shift->_list_cmd("NLST", @_); } sub dir { shift->_list_cmd("LIST", @_); } sub pasv { my $ftp = shift; @_ and croak 'usage: $ftp->port()'; return $ftp->epsv if $ftp->sockdomain != AF_INET; delete ${*$ftp}{net_ftp_intern_port}; if ( $ftp->_PASV && $ftp->message =~ m{(\d+,\d+,\d+,\d+),(\d+),(\d+)} ) { my $port = 256 * $2 + $3; ( my $ip = $1 ) =~s{,}{.}g; return ${*$ftp}{net_ftp_pasv} = [ $ip,$port ]; } return; } sub epsv { my $ftp = shift; @_ and croak 'usage: $ftp->epsv()'; delete ${*$ftp}{net_ftp_intern_port}; $ftp->_EPSV && $ftp->message =~ m{\(([\x33-\x7e])\1\1(\d+)\1\)} ? ${*$ftp}{net_ftp_pasv} = [ $ftp->peerhost, $2 ] : undef; } sub unique_name { my $ftp = shift; ${*$ftp}{'net_ftp_unique'} || undef; } sub supported { @_ == 2 or croak 'usage: $ftp->supported( CMD )'; my $ftp = shift; my $cmd = uc shift; my $hash = ${*$ftp}{'net_ftp_supported'} ||= {}; return $hash->{$cmd} if exists $hash->{$cmd}; return $hash->{$cmd} = 1 if $ftp->feature($cmd); return $hash->{$cmd} = 0 unless $ftp->_HELP($cmd); my $text = $ftp->message; if ($text =~ /following.+commands/i) { $text =~ s/^.*\n//; while ($text =~ /(\*?)(\w+)(\*?)/sg) { $hash->{"\U$2"} = !length("$1$3"); } } else { $hash->{$cmd} = $text !~ /unimplemented/i; } $hash->{$cmd} ||= 0; } ## ## Deprecated methods ## sub lsl { carp "Use of Net::FTP::lsl deprecated, use 'dir'" if $^W; goto &dir; } sub authorise { carp "Use of Net::FTP::authorise deprecated, use 'authorize'" if $^W; goto &authorize; } ## ## Private methods ## sub _extract_path { my ($ftp, $path) = @_; # This tries to work both with and without the quote doubling # convention (RFC 959 requires it, but the first 3 servers I checked # didn't implement it). It will fail on a server which uses a quote in # the message which isn't a part of or surrounding the path. $ftp->ok && $ftp->message =~ /(?:^|\s)\"(.*)\"(?:$|\s)/ && ($path = $1) =~ s/\"\"/\"/g; $path; } ## ## Communication methods ## sub _dataconn { my $ftp = shift; my $pkg = "Net::FTP::" . $ftp->type; eval "require " . $pkg ## no critic (BuiltinFunctions::ProhibitStringyEval) or croak("cannot load $pkg required for type ".$ftp->type); $pkg =~ s/ /_/g; delete ${*$ftp}{net_ftp_dataconn}; my $conn; my $pasv = ${*$ftp}{net_ftp_pasv}; if ($pasv) { $conn = $pkg->new( PeerAddr => $pasv->[0], PeerPort => $pasv->[1], LocalAddr => ${*$ftp}{net_ftp_localaddr}, $family_key => ${*$ftp}{net_ftp_domain}, Timeout => $ftp->timeout, can_ssl() ? ( SSL_startHandshake => 0, $ftp->is_SSL ? ( SSL_reuse_ctx => $ftp, SSL_verifycn_name => ${*$ftp}{net_ftp_tlsargs}{SSL_verifycn_name}, # This will cause the use of SNI if supported by IO::Socket::SSL. $ftp->can_client_sni ? ( SSL_hostname => ${*$ftp}{net_ftp_tlsargs}{SSL_hostname} ):(), ) :( %{${*$ftp}{net_ftp_tlsargs}} ), ):(), ) or return; } elsif (my $listen = delete ${*$ftp}{net_ftp_listen}) { $conn = $listen->accept($pkg) or return; $conn->timeout($ftp->timeout); close($listen); } else { croak("no listener in active mode"); } if (( ${*$ftp}{net_ftp_tlsprot} || '') eq 'P') { if ($conn->connect_SSL) { # SSL handshake ok } else { carp("failed to ssl upgrade dataconn: $IO::Socket::SSL::SSL_ERROR"); return; } } ${*$ftp}{net_ftp_dataconn} = $conn; ${*$conn} = ""; ${*$conn}{net_ftp_cmd} = $ftp; ${*$conn}{net_ftp_blksize} = ${*$ftp}{net_ftp_blksize}; return $conn; } sub _list_cmd { my $ftp = shift; my $cmd = uc shift; delete ${*$ftp}{'net_ftp_port'}; delete ${*$ftp}{'net_ftp_pasv'}; my $data = $ftp->_data_cmd($cmd, @_); return unless (defined $data); require Net::FTP::A; bless $data, "Net::FTP::A"; # Force ASCII mode my $databuf = ''; my $buf = ''; my $blksize = ${*$ftp}{'net_ftp_blksize'}; while ($data->read($databuf, $blksize)) { $buf .= $databuf; } my $list = [split(/\n/, $buf)]; $data->close(); if (EBCDIC) { for (@$list) { $_ = $ftp->toebcdic($_) } } wantarray ? @{$list} : $list; } sub _data_cmd { my $ftp = shift; my $cmd = uc shift; my $ok = 1; my $where = delete ${*$ftp}{'net_ftp_rest'} || 0; my $arg; for my $arg (@_) { croak("Bad argument '$arg'\n") if $arg =~ /[\r\n]/s; } if ( ${*$ftp}{'net_ftp_passive'} && !defined ${*$ftp}{'net_ftp_pasv'} && !defined ${*$ftp}{'net_ftp_port'}) { return unless defined $ftp->pasv; if ($where and !$ftp->_REST($where)) { my ($status, $message) = ($ftp->status, $ftp->message); $ftp->abort; $ftp->set_status($status, $message); return; } # first send command, then open data connection # otherwise the peer might not do a full accept (with SSL # handshake if PROT P) $ftp->command($cmd, @_); my $data = $ftp->_dataconn(); if (CMD_INFO == $ftp->response()) { $data->reading if $data && $cmd =~ /RETR|LIST|NLST|MLSD/; return $data; } $data->_close if $data; return; } $ok = $ftp->port unless (defined ${*$ftp}{'net_ftp_port'} || defined ${*$ftp}{'net_ftp_pasv'}); $ok = $ftp->_REST($where) if $ok && $where; return unless $ok; if ($cmd =~ /(STOR|APPE|STOU)/ and exists ${*$ftp}{net_ftp_allo} and $ftp->supported("ALLO")) { $ftp->_ALLO(delete ${*$ftp}{net_ftp_allo}) or return; } $ftp->command($cmd, @_); return 1 if (defined ${*$ftp}{'net_ftp_pasv'}); $ok = CMD_INFO == $ftp->response(); return $ok unless exists ${*$ftp}{'net_ftp_intern_port'}; if ($ok) { my $data = $ftp->_dataconn(); $data->reading if $data && $cmd =~ /RETR|LIST|NLST|MLSD/; return $data; } close(delete ${*$ftp}{'net_ftp_listen'}); return; } ## ## Over-ride methods (Net::Cmd) ## sub debug_text { $_[2] =~ /^(pass|resp|acct)/i ? "$1 ....\n" : $_[2]; } sub command { my $ftp = shift; delete ${*$ftp}{'net_ftp_port'}; $ftp->SUPER::command(@_); } sub response { my $ftp = shift; my $code = $ftp->SUPER::response() || 5; # assume 500 if undef delete ${*$ftp}{'net_ftp_pasv'} if ($code != CMD_MORE && $code != CMD_INFO); $code; } sub parse_response { return ($1, $2 eq "-") if $_[1] =~ s/^(\d\d\d)([- ]?)//o; my $ftp = shift; # Darn MS FTP server is a load of CRAP !!!! # Expect to see undef here. return () unless 0 + (${*$ftp}{'net_cmd_code'} || 0); (${*$ftp}{'net_cmd_code'}, 1); } ## ## Allow 2 servers to talk directly ## sub pasv_xfer_unique { my ($sftp, $sfile, $dftp, $dfile) = @_; $sftp->pasv_xfer($sfile, $dftp, $dfile, 1); } sub pasv_xfer { my ($sftp, $sfile, $dftp, $dfile, $unique) = @_; ($dfile = $sfile) =~ s#.*/## unless (defined $dfile); my $port = $sftp->pasv or return; $dftp->port($port) or return; return unless ($unique ? $dftp->stou($dfile) : $dftp->stor($dfile)); unless ($sftp->retr($sfile) && $sftp->response == CMD_INFO) { $sftp->retr($sfile); $dftp->abort; $dftp->response(); return; } $dftp->pasv_wait($sftp); } sub pasv_wait { @_ == 2 or croak 'usage: $ftp->pasv_wait(NON_PASV_FTP)'; my ($ftp, $non_pasv) = @_; my ($file, $rin, $rout); vec($rin = '', fileno($ftp), 1) = 1; select($rout = $rin, undef, undef, undef); my $dres = $ftp->response(); my $sres = $non_pasv->response(); return unless $dres == CMD_OK && $sres == CMD_OK; return unless $ftp->ok() && $non_pasv->ok(); return $1 if $ftp->message =~ /unique file name:\s*(\S*)\s*\)/; return $1 if $non_pasv->message =~ /unique file name:\s*(\S*)\s*\)/; return 1; } sub feature { @_ == 2 or croak 'usage: $ftp->feature( NAME )'; my ($ftp, $feat) = @_; my $feature = ${*$ftp}{net_ftp_feature} ||= do { my @feat; # Example response # 211-Features: # MDTM # REST STREAM # SIZE # 211 End @feat = map { /^\s+(.*\S)/ } $ftp->message if $ftp->_FEAT; \@feat; }; return grep { /^\Q$feat\E\b/i } @$feature; } sub cmd { shift->command(@_)->response() } ######################################## # # RFC959 + RFC2428 + RFC4217 commands # sub _ABOR { shift->command("ABOR")->response() == CMD_OK } sub _ALLO { shift->command("ALLO", @_)->response() == CMD_OK } sub _CDUP { shift->command("CDUP")->response() == CMD_OK } sub _NOOP { shift->command("NOOP")->response() == CMD_OK } sub _PASV { shift->command("PASV")->response() == CMD_OK } sub _QUIT { shift->command("QUIT")->response() == CMD_OK } sub _DELE { shift->command("DELE", @_)->response() == CMD_OK } sub _CWD { shift->command("CWD", @_)->response() == CMD_OK } sub _PORT { shift->command("PORT", @_)->response() == CMD_OK } sub _RMD { shift->command("RMD", @_)->response() == CMD_OK } sub _MKD { shift->command("MKD", @_)->response() == CMD_OK } sub _PWD { shift->command("PWD", @_)->response() == CMD_OK } sub _TYPE { shift->command("TYPE", @_)->response() == CMD_OK } sub _RNTO { shift->command("RNTO", @_)->response() == CMD_OK } sub _RESP { shift->command("RESP", @_)->response() == CMD_OK } sub _MDTM { shift->command("MDTM", @_)->response() == CMD_OK } sub _SIZE { shift->command("SIZE", @_)->response() == CMD_OK } sub _HELP { shift->command("HELP", @_)->response() == CMD_OK } sub _STAT { shift->command("STAT", @_)->response() == CMD_OK } sub _FEAT { shift->command("FEAT", @_)->response() == CMD_OK } sub _PBSZ { shift->command("PBSZ", @_)->response() == CMD_OK } sub _PROT { shift->command("PROT", @_)->response() == CMD_OK } sub _CCC { shift->command("CCC", @_)->response() == CMD_OK } sub _EPRT { shift->command("EPRT", @_)->response() == CMD_OK } sub _EPSV { shift->command("EPSV", @_)->response() == CMD_OK } sub _APPE { shift->command("APPE", @_)->response() == CMD_INFO } sub _LIST { shift->command("LIST", @_)->response() == CMD_INFO } sub _NLST { shift->command("NLST", @_)->response() == CMD_INFO } sub _RETR { shift->command("RETR", @_)->response() == CMD_INFO } sub _STOR { shift->command("STOR", @_)->response() == CMD_INFO } sub _STOU { shift->command("STOU", @_)->response() == CMD_INFO } sub _RNFR { shift->command("RNFR", @_)->response() == CMD_MORE } sub _REST { shift->command("REST", @_)->response() == CMD_MORE } sub _PASS { shift->command("PASS", @_)->response() } sub _ACCT { shift->command("ACCT", @_)->response() } sub _AUTH { shift->command("AUTH", @_)->response() } sub _USER { my $ftp = shift; my $ok = $ftp->command("USER", @_)->response(); # A certain brain dead firewall :-) $ok = $ftp->command("user", @_)->response() unless $ok == CMD_MORE or $ok == CMD_OK; $ok; } sub _SMNT { shift->unsupported(@_) } sub _MODE { shift->unsupported(@_) } sub _SYST { shift->unsupported(@_) } sub _STRU { shift->unsupported(@_) } sub _REIN { shift->unsupported(@_) } { # Session Cache with single entry # used to make sure that we reuse same session for control and data channels package Net::FTP::_SSL_SingleSessionCache; sub new { my $x; return bless \$x,shift } sub add_session { my ($cache,$key,$session) = @_; Net::SSLeay::SESSION_free($$cache) if $$cache; $$cache = $session; } sub get_session { my $cache = shift; return $$cache } sub DESTROY { my $cache = shift; Net::SSLeay::SESSION_free($$cache) if $$cache; } } 1; __END__ =head1 NAME Net::FTP - FTP Client class =head1 SYNOPSIS use Net::FTP; $ftp = Net::FTP->new("some.host.name", Debug => 0) or die "Cannot connect to some.host.name: $@"; $ftp->login("anonymous",'-anonymous@') or die "Cannot login ", $ftp->message; $ftp->cwd("/pub") or die "Cannot change working directory ", $ftp->message; $ftp->get("that.file") or die "get failed ", $ftp->message; $ftp->quit; =head1 DESCRIPTION C is a class implementing a simple FTP client in Perl as described in RFC959. It provides wrappers for the commonly used subset of the RFC959 commands. If L or L is installed it also provides support for IPv6 as defined in RFC2428. And with L installed it provides support for implicit FTPS and explicit FTPS as defined in RFC4217. The Net::FTP class is a subclass of Net::Cmd and (depending on avaibility) of IO::Socket::IP, IO::Socket::INET6 or IO::Socket::INET. =head1 OVERVIEW FTP stands for File Transfer Protocol. It is a way of transferring files between networked machines. The protocol defines a client (whose commands are provided by this module) and a server (not implemented in this module). Communication is always initiated by the client, and the server responds with a message and a status code (and sometimes with data). The FTP protocol allows files to be sent to or fetched from the server. Each transfer involves a B (on the client) and a B (on the server). In this module, the same file name will be used for both local and remote if only one is specified. This means that transferring remote file C will try to put that file in C locally, unless you specify a local file name. The protocol also defines several standard B which the file can undergo during transfer. These are ASCII, EBCDIC, binary, and byte. ASCII is the default type, and indicates that the sender of files will translate the ends of lines to a standard representation which the receiver will then translate back into their local representation. EBCDIC indicates the file being transferred is in EBCDIC format. Binary (also known as image) format sends the data as a contiguous bit stream. Byte format transfers the data as bytes, the values of which remain the same regardless of differences in byte size between the two machines (in theory - in practice you should only use this if you really know what you're doing). This class does not support the EBCDIC or byte formats, and will default to binary instead if they are attempted. =head1 CONSTRUCTOR =over 4 =item new ([ HOST ] [, OPTIONS ]) This is the constructor for a new Net::FTP object. C is the name of the remote host to which an FTP connection is required. C is optional. If C is not given then it may instead be passed as the C option described below. C are passed in a hash like fashion, using key and value pairs. Possible options are: B - FTP host to connect to. It may be a single scalar, as defined for the C option in L, or a reference to an array with hosts to try in turn. The L method will return the value which was used to connect to the host. B - The name of a machine which acts as an FTP firewall. This can be overridden by an environment variable C. If specified, and the given host cannot be directly connected to, then the connection is made to the firewall machine and the string C<@hostname> is appended to the login identifier. This kind of setup is also referred to as an ftp proxy. B - The type of firewall running on the machine indicated by B. This can be overridden by an environment variable C. For a list of permissible types, see the description of ftp_firewall_type in L. B - This is the block size that Net::FTP will use when doing transfers. (defaults to 10240) B - The port number to connect to on the remote machine for the FTP connection B - If the connection should be done from start with SSL, contrary to later upgrade with C. B - SSL arguments which will be applied when upgrading the control or data connection to SSL. You can use SSL arguments as documented in L, but it will usually use the right arguments already. B - Set a timeout value in seconds (defaults to 120) B - debug level (see the debug method in L) B - If set to a non-zero value then all data transfers will be done using passive mode. If set to zero then data transfers will be done using active mode. If the machine is connected to the Internet directly, both passive and active mode should work equally well. Behind most firewall and NAT configurations passive mode has a better chance of working. However, in some rare firewall configurations, active mode actually works when passive mode doesn't. Some really old FTP servers might not implement passive transfers. If not specified, then the transfer mode is set by the environment variable C or if that one is not set by the settings done by the F utility. If none of these apply then passive mode is used. B - If given a reference to a file handle (e.g., C<\*STDERR>), print hash marks (#) on that filehandle every 1024 bytes. This simply invokes the C method for you, so that hash marks are displayed for all transfers. You can, of course, call C explicitly whenever you'd like. B - Local address to use for all socket connections. This argument will be passed to the super class, i.e. L or L. B - Domain to use, i.e. AF_INET or AF_INET6. This argument will be passed to the IO::Socket super class. This can be used to enforce IPv4 even with L which would default to IPv6. B is accepted as alternative name for B. If the constructor fails undef will be returned and an error message will be in $@ =back =head1 METHODS Unless otherwise stated all methods return either a I or I value, with I meaning that the operation was a success. When a method states that it returns a value, failure will be returned as I or an empty list. C inherits from C so methods defined in C may be used to send commands to the remote FTP server in addition to the methods documented here. =over 4 =item login ([LOGIN [,PASSWORD [, ACCOUNT] ] ]) Log into the remote FTP server with the given login information. If no arguments are given then the C uses the C package to lookup the login information for the connected host. If no information is found then a login of I is used. If no password is given and the login is I then I will be used for password. If the connection is via a firewall then the C method will be called with no arguments. =item starttls () Upgrade existing plain connection to SSL. The SSL arguments have to be given in C already because they are needed for data connections too. =item stoptls () Downgrade existing SSL connection back to plain. This is needed to work with some FTP helpers at firewalls, which need to see the PORT and PASV commands and responses to dynamically open the necessary ports. In this case C is usually only done to protect the authorization. =item prot ( LEVEL ) Set what type of data channel protection the client and server will be using. Only Cs "C" (clear) and "P" (private) are supported. =item host () Returns the value used by the constructor, and passed to the IO::Socket super class to connect to the host. =item account( ACCT ) Set a string identifying the user's account. =item authorize ( [AUTH [, RESP]]) This is a protocol used by some firewall ftp proxies. It is used to authorise the user to send data out. If both arguments are not specified then C uses C to do a lookup. =item site (ARGS) Send a SITE command to the remote server and wait for a response. Returns most significant digit of the response code. =item ascii () Transfer file in ASCII. CRLF translation will be done if required =item binary () Transfer file in binary mode. No transformation will be done. B: If both server and client machines use the same line ending for text files, then it will be faster to transfer all files in binary mode. =item type ( [ TYPE ] ) Set or get if files will be transferred in ASCII or binary mode. =item rename ( OLDNAME, NEWNAME ) Rename a file on the remote FTP server from C to C. This is done by sending the RNFR and RNTO commands. =item delete ( FILENAME ) Send a request to the server to delete C. =item cwd ( [ DIR ] ) Attempt to change directory to the directory given in C<$dir>. If C<$dir> is C<"..">, the FTP C command is used to attempt to move up one directory. If no directory is given then an attempt is made to change the directory to the root directory. =item cdup () Change directory to the parent of the current directory. =item passive ( [ PASSIVE ] ) Set or get if data connections will be initiated in passive mode. =item pwd () Returns the full pathname of the current directory. =item restart ( WHERE ) Set the byte offset at which to begin the next data transfer. Net::FTP simply records this value and uses it when during the next data transfer. For this reason this method will not return an error, but setting it may cause a subsequent data transfer to fail. =item rmdir ( DIR [, RECURSE ]) Remove the directory with the name C. If C is I then C will attempt to delete everything inside the directory. =item mkdir ( DIR [, RECURSE ]) Create a new directory with the name C. If C is I then C will attempt to create all the directories in the given path. Returns the full pathname to the new directory. =item alloc ( SIZE [, RECORD_SIZE] ) The alloc command allows you to give the ftp server a hint about the size of the file about to be transferred using the ALLO ftp command. Some storage systems use this to make intelligent decisions about how to store the file. The C argument represents the size of the file in bytes. The C argument indicates a maximum record or page size for files sent with a record or page structure. The size of the file will be determined, and sent to the server automatically for normal files so that this method need only be called if you are transferring data from a socket, named pipe, or other stream not associated with a normal file. =item ls ( [ DIR ] ) Get a directory listing of C, or the current directory. In an array context, returns a list of lines returned from the server. In a scalar context, returns a reference to a list. =item dir ( [ DIR ] ) Get a directory listing of C, or the current directory in long format. In an array context, returns a list of lines returned from the server. In a scalar context, returns a reference to a list. =item get ( REMOTE_FILE [, LOCAL_FILE [, WHERE]] ) Get C from the server and store locally. C may be a filename or a filehandle. If not specified, the file will be stored in the current directory with the same leafname as the remote file. If C is given then the first C bytes of the file will not be transferred, and the remaining bytes will be appended to the local file if it already exists. Returns C, or the generated local file name if C is not given. If an error was encountered undef is returned. =item put ( LOCAL_FILE [, REMOTE_FILE ] ) Put a file on the remote server. C may be a name or a filehandle. If C is a filehandle then C must be specified. If C is not specified then the file will be stored in the current directory with the same leafname as C. Returns C, or the generated remote filename if C is not given. B: If for some reason the transfer does not complete and an error is returned then the contents that had been transferred will not be remove automatically. =item put_unique ( LOCAL_FILE [, REMOTE_FILE ] ) Same as put but uses the C command. Returns the name of the file on the server. =item append ( LOCAL_FILE [, REMOTE_FILE ] ) Same as put but appends to the file on the remote server. Returns C, or the generated remote filename if C is not given. =item unique_name () Returns the name of the last file stored on the server using the C command. =item mdtm ( FILE ) Returns the I of the given file =item size ( FILE ) Returns the size in bytes for the given file as stored on the remote server. B: The size reported is the size of the stored file on the remote server. If the file is subsequently transferred from the server in ASCII mode and the remote server and local machine have different ideas about "End Of Line" then the size of file on the local machine after transfer may be different. =item supported ( CMD ) Returns TRUE if the remote server supports the given command. =item hash ( [FILEHANDLE_GLOB_REF],[ BYTES_PER_HASH_MARK] ) Called without parameters, or with the first argument false, hash marks are suppressed. If the first argument is true but not a reference to a file handle glob, then \*STDERR is used. The second argument is the number of bytes per hash mark printed, and defaults to 1024. In all cases the return value is a reference to an array of two: the filehandle glob reference and the bytes per hash mark. =item feature ( NAME ) Determine if the server supports the specified feature. The return value is a list of lines the server responded with to describe the options that it supports for the given feature. If the feature is unsupported then the empty list is returned. if ($ftp->feature( 'MDTM' )) { # Do something } if (grep { /\bTLS\b/ } $ftp->feature('AUTH')) { # Server supports TLS } =back The following methods can return different results depending on how they are called. If the user explicitly calls either of the C or C methods then these methods will return a I or I value. If the user does not call either of these methods then the result will be a reference to a C based object. =over 4 =item nlst ( [ DIR ] ) Send an C command to the server, with an optional parameter. =item list ( [ DIR ] ) Same as C but using the C command =item retr ( FILE ) Begin the retrieval of a file called C from the remote server. =item stor ( FILE ) Tell the server that you wish to store a file. C is the name of the new file that should be created. =item stou ( FILE ) Same as C but using the C command. The name of the unique file which was created on the server will be available via the C method after the data connection has been closed. =item appe ( FILE ) Tell the server that we want to append some data to the end of a file called C. If this file does not exist then create it. =back If for some reason you want to have complete control over the data connection, this includes generating it and calling the C method when required, then the user can use these methods to do so. However calling these methods only affects the use of the methods above that can return a data connection. They have no effect on methods C, C, C and those that do not require data connections. =over 4 =item port ( [ PORT ] ) =item eprt ( [ PORT ] ) Send a C (IPv4) or C (IPv6) command to the server. If C is specified then it is sent to the server. If not, then a listen socket is created and the correct information sent to the server. =item pasv () =item epsv () Tell the server to go into passive mode (C for IPv4, C for IPv6). Returns the text that represents the port on which the server is listening, this text is in a suitable form to send to another ftp server using the C or C method. =back The following methods can be used to transfer files between two remote servers, providing that these two servers can connect directly to each other. =over 4 =item pasv_xfer ( SRC_FILE, DEST_SERVER [, DEST_FILE ] ) This method will do a file transfer between two remote ftp servers. If C is omitted then the leaf name of C will be used. =item pasv_xfer_unique ( SRC_FILE, DEST_SERVER [, DEST_FILE ] ) Like C but the file is stored on the remote server using the STOU command. =item pasv_wait ( NON_PASV_SERVER ) This method can be used to wait for a transfer to complete between a passive server and a non-passive server. The method should be called on the passive server with the C object for the non-passive server passed as an argument. =item abort () Abort the current data transfer. =item quit () Send the QUIT command to the remote FTP server and close the socket connection. =back =head2 Methods for the adventurous =over 4 =item quot (CMD [,ARGS]) Send a command, that Net::FTP does not directly support, to the remote server and wait for a response. Returns most significant digit of the response code. B This call should only be used on commands that do not require data connections. Misuse of this method can hang the connection. =item can_inet6 () Returns whether we can use IPv6. =item can_ssl () Returns whether we can use SSL. =back =head1 THE dataconn CLASS Some of the methods defined in C return an object which will be derived from the C class. See L for more details. =head1 UNIMPLEMENTED The following RFC959 commands have not been implemented: =over 4 =item B Mount a different file system structure without changing login or accounting information. =item B Ask the server for "helpful information" (that's what the RFC says) on the commands it accepts. =item B Specifies transfer mode (stream, block or compressed) for file to be transferred. =item B Request remote server system identification. =item B Request remote server status. =item B Specifies file structure for file to be transferred. =item B Reinitialize the connection, flushing all I/O and account information. =back =head1 REPORTING BUGS When reporting bugs/problems please include as much information as possible. It may be difficult for me to reproduce the problem as almost every setup is different. A small script which yields the problem will probably be of help. It would also be useful if this script was run with the extra options C<< Debug => 1 >> passed to the constructor, and the output sent with the bug report. If you cannot include a small script then please include a Debug trace from a run of your program which does yield the problem. =head1 AUTHOR Graham Barr EFE. Steve Hay EFE is now maintaining libnet as of version 1.22_02. =head1 SEE ALSO L, L, L ftp(1), ftpd(8), RFC 959, RFC 2428, RFC 4217 http://www.ietf.org/rfc/rfc959.txt http://www.ietf.org/rfc/rfc2428.txt http://www.ietf.org/rfc/rfc4217.txt =head1 USE EXAMPLES For an example of the use of Net::FTP see =over 4 =item http://www.csh.rit.edu/~adam/Progs/ C is a program that can retrieve, send, or list files via the FTP protocol in a non-interactive manner. =back =head1 CREDITS Henry Gabryjelski - for the suggestion of creating directories recursively. Nathan Torkington - for some input on the documentation. Roderick Schertler - for various inputs =head1 COPYRIGHT Copyright (C) 1995-2004 Graham Barr. All rights reserved. Copyright (C) 2013-2017 Steve Hay. All rights reserved. =head1 LICENCE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e. under the terms of either the GNU General Public License or the Artistic License, as specified in the F file. =cut PK f1]tF HTTPS.pmnu[package Net::HTTPS; $Net::HTTPS::VERSION = '6.17'; use strict; use warnings; # Figure out which SSL implementation to use use vars qw($SSL_SOCKET_CLASS); if ($SSL_SOCKET_CLASS) { # somebody already set it } elsif ($SSL_SOCKET_CLASS = $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS}) { unless ($SSL_SOCKET_CLASS =~ /^(IO::Socket::SSL|Net::SSL)\z/) { die "Bad socket class [$SSL_SOCKET_CLASS]"; } eval "require $SSL_SOCKET_CLASS"; die $@ if $@; } elsif ($IO::Socket::SSL::VERSION) { $SSL_SOCKET_CLASS = "IO::Socket::SSL"; # it was already loaded } elsif ($Net::SSL::VERSION) { $SSL_SOCKET_CLASS = "Net::SSL"; } else { eval { require IO::Socket::SSL; }; if ($@) { my $old_errsv = $@; eval { require Net::SSL; # from Crypt-SSLeay }; if ($@) { $old_errsv =~ s/\s\(\@INC contains:.*\)/)/g; die $old_errsv . $@; } $SSL_SOCKET_CLASS = "Net::SSL"; } else { $SSL_SOCKET_CLASS = "IO::Socket::SSL"; } } require Net::HTTP::Methods; our @ISA=($SSL_SOCKET_CLASS, 'Net::HTTP::Methods'); sub configure { my($self, $cnf) = @_; $self->http_configure($cnf); } sub http_connect { my($self, $cnf) = @_; if ($self->isa("Net::SSL")) { if ($cnf->{SSL_verify_mode}) { if (my $f = $cnf->{SSL_ca_file}) { $ENV{HTTPS_CA_FILE} = $f; } if (my $f = $cnf->{SSL_ca_path}) { $ENV{HTTPS_CA_DIR} = $f; } } if ($cnf->{SSL_verifycn_scheme}) { $@ = "Net::SSL from Crypt-SSLeay can't verify hostnames; either install IO::Socket::SSL or turn off verification by setting the PERL_LWP_SSL_VERIFY_HOSTNAME environment variable to 0"; return undef; } } $self->SUPER::configure($cnf); } sub http_default_port { 443; } if ($SSL_SOCKET_CLASS eq "Net::SSL") { # The underlying SSLeay classes fails to work if the socket is # placed in non-blocking mode. This override of the blocking # method makes sure it stays the way it was created. *blocking = sub { }; } 1; =pod =encoding UTF-8 =head1 NAME Net::HTTPS - Low-level HTTP over SSL/TLS connection (client) =head1 VERSION version 6.17 =head1 DESCRIPTION The C is a low-level HTTP over SSL/TLS client. The interface is the same as the interface for C, but the constructor takes additional parameters as accepted by L. The C object is an C too, which makes it inherit additional methods from that base class. For historical reasons this module also supports using C (from the Crypt-SSLeay distribution) as its SSL driver and base class. This base is automatically selected if available and C isn't. You might also force which implementation to use by setting $Net::HTTPS::SSL_SOCKET_CLASS before loading this module. If not set this variable is initialized from the C environment variable. =head1 ENVIRONMENT You might set the C environment variable to the name of the base SSL implementation (and Net::HTTPS base class) to use. The default is C. Currently the only other supported value is C. =head1 SEE ALSO L, L =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001-2017 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: Low-level HTTP over SSL/TLS connection (client) PK f1],Netrc.pmnu[# Net::Netrc.pm # # Copyright (C) 1995-1998 Graham Barr. All rights reserved. # Copyright (C) 2013-2014 Steve Hay. All rights reserved. # This module is free software; you can redistribute it and/or modify it under # the same terms as Perl itself, i.e. under the terms of either the GNU General # Public License or the Artistic License, as specified in the F file. package Net::Netrc; use 5.008001; use strict; use warnings; use Carp; use FileHandle; our $VERSION = "3.11"; our $TESTING; my %netrc = (); sub _readrc { my($class, $host) = @_; my ($home, $file); if ($^O eq "MacOS") { $home = $ENV{HOME} || `pwd`; chomp($home); $file = ($home =~ /:$/ ? $home . "netrc" : $home . ":netrc"); } else { # Some OS's don't have "getpwuid", so we default to $ENV{HOME} $home = eval { (getpwuid($>))[7] } || $ENV{HOME}; $home ||= $ENV{HOMEDRIVE} . ($ENV{HOMEPATH} || '') if defined $ENV{HOMEDRIVE}; if (-e $home . "/.netrc") { $file = $home . "/.netrc"; } elsif (-e $home . "/_netrc") { $file = $home . "/_netrc"; } else { return unless $TESTING; } } my ($login, $pass, $acct) = (undef, undef, undef); my $fh; local $_; $netrc{default} = undef; # OS/2 and Win32 do not handle stat in a way compatible with this check :-( unless ($^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'MacOS' || $^O =~ /^cygwin/) { my @stat = stat($file); if (@stat) { if ($stat[2] & 077) { ## no critic (ValuesAndExpressions::ProhibitLeadingZeros) carp "Bad permissions: $file"; return; } if ($stat[4] != $<) { carp "Not owner: $file"; return; } } } if ($fh = FileHandle->new($file, "r")) { my ($mach, $macdef, $tok, @tok) = (0, 0); while (<$fh>) { undef $macdef if /\A\n\Z/; if ($macdef) { push(@$macdef, $_); next; } s/^\s*//; chomp; while (length && s/^("((?:[^"]+|\\.)*)"|((?:[^\\\s]+|\\.)*))\s*//) { (my $tok = $+) =~ s/\\(.)/$1/g; push(@tok, $tok); } TOKEN: while (@tok) { if ($tok[0] eq "default") { shift(@tok); $mach = bless {}, $class; $netrc{default} = [$mach]; next TOKEN; } last TOKEN unless @tok > 1; $tok = shift(@tok); if ($tok eq "machine") { my $host = shift @tok; $mach = bless {machine => $host}, $class; $netrc{$host} = [] unless exists($netrc{$host}); push(@{$netrc{$host}}, $mach); } elsif ($tok =~ /^(login|password|account)$/) { next TOKEN unless $mach; my $value = shift @tok; # Following line added by rmerrell to remove '/' escape char in .netrc $value =~ s/\/\\/\\/g; $mach->{$1} = $value; } elsif ($tok eq "macdef") { next TOKEN unless $mach; my $value = shift @tok; $mach->{macdef} = {} unless exists $mach->{macdef}; $macdef = $mach->{machdef}{$value} = []; } } } $fh->close(); } } sub lookup { my ($class, $mach, $login) = @_; $class->_readrc() unless exists $netrc{default}; $mach ||= 'default'; undef $login if $mach eq 'default'; if (exists $netrc{$mach}) { if (defined $login) { foreach my $m (@{$netrc{$mach}}) { return $m if (exists $m->{login} && $m->{login} eq $login); } return; } return $netrc{$mach}->[0]; } return $netrc{default}->[0] if defined $netrc{default}; return; } sub login { my $me = shift; exists $me->{login} ? $me->{login} : undef; } sub account { my $me = shift; exists $me->{account} ? $me->{account} : undef; } sub password { my $me = shift; exists $me->{password} ? $me->{password} : undef; } sub lpa { my $me = shift; ($me->login, $me->password, $me->account); } 1; __END__ =head1 NAME Net::Netrc - OO interface to users netrc file =head1 SYNOPSIS use Net::Netrc; $mach = Net::Netrc->lookup('some.machine'); $login = $mach->login; ($login, $password, $account) = $mach->lpa; =head1 DESCRIPTION C is a class implementing a simple interface to the .netrc file used as by the ftp program. C also implements security checks just like the ftp program, these checks are, first that the .netrc file must be owned by the user and second the ownership permissions should be such that only the owner has read and write access. If these conditions are not met then a warning is output and the .netrc file is not read. =head1 THE .netrc FILE The .netrc file contains login and initialization information used by the auto-login process. It resides in the user's home directory. The following tokens are recognized; they may be separated by spaces, tabs, or new-lines: =over 4 =item machine name Identify a remote machine name. The auto-login process searches the .netrc file for a machine token that matches the remote machine specified. Once a match is made, the subsequent .netrc tokens are processed, stopping when the end of file is reached or an- other machine or a default token is encountered. =item default This is the same as machine name except that default matches any name. There can be only one default token, and it must be after all machine tokens. This is normally used as: default login anonymous password user@site thereby giving the user automatic anonymous login to machines not specified in .netrc. =item login name Identify a user on the remote machine. If this token is present, the auto-login process will initiate a login using the specified name. =item password string Supply a password. If this token is present, the auto-login process will supply the specified string if the remote server requires a password as part of the login process. =item account string Supply an additional account password. If this token is present, the auto-login process will supply the specified string if the remote server requires an additional account password. =item macdef name Define a macro. C only parses this field to be compatible with I. =back =head1 CONSTRUCTOR The constructor for a C object is not called new as it does not really create a new object. But instead is called C as this is essentially what it does. =over 4 =item lookup ( MACHINE [, LOGIN ]) Lookup and return a reference to the entry for C. If C is given then the entry returned will have the given login. If C is not given then the first entry in the .netrc file for C will be returned. If a matching entry cannot be found, and a default entry exists, then a reference to the default entry is returned. If there is no matching entry found and there is no default defined, or no .netrc file is found, then C is returned. =back =head1 METHODS =over 4 =item login () Return the login id for the netrc entry =item password () Return the password for the netrc entry =item account () Return the account information for the netrc entry =item lpa () Return a list of login, password and account information for the netrc entry =back =head1 AUTHOR Graham Barr EFE. Steve Hay EFE is now maintaining libnet as of version 1.22_02. =head1 SEE ALSO L, L =head1 COPYRIGHT Copyright (C) 1995-1998 Graham Barr. All rights reserved. Copyright (C) 2013-2014 Steve Hay. All rights reserved. =head1 LICENCE This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e. under the terms of either the GNU General Public License or the Artistic License, as specified in the F file. =cut PKp0]q protoent.pmnu[PKp0]  hostent.pmnu[PKp0]6 B servent.pmnu[PKp0]]8]8)Ping.pmnu[PKp0]y4 gbnetent.pmnu[PKR1]Wp{{ !tSSLeay.podnu[PKR1]V~**/SSLeay/Handle.pmnu[PKR1]^ nSSLeay.pmnu[PK f1] SSPOP3.pmnu[PK f1]c=E  VHTTP/NB.pmnu[PK f1]%CC)`HTTP/Methods.pmnu[PK f1]|dz+ + -Domain.pmnu[PK f1]7XkuPuPCmd.pmnu[PK f1]_(!(! < Config.pmnu[PK f1]pp6 NNTP.pmnu[PK f1]s:ppD SMTP.pmnu[PK f1]ť''' HTTP.pmnu[PK f1]IH{{O FTP/I.pmnu[PK f1]B V FTP/dataconn.pmnu[PK f1]c;e FTP/E.pmnu[PK f1]8` ` f FTP/A.pmnu[PK f1]|Ip FTP/L.pmnu[PK f1] * p libnetFAQ.podnu[PK f1]6 r Time.pmnu[PK f1]Z; FTP.pmnu[PK f1]tF Q HTTPS.pmnu[PK f1],+_ Netrc.pmnu[PKS~