Net::SSLeay#

📦 max

Net::SSLeay - Perl bindings for OpenSSL’s libssl and libcrypto.

TLS connections, certificates, keys, digests and the rest of OpenSSL, one Perl function per C function: Net::SSLeay::CTX_new is SSL_CTX_new, Net::SSLeay::X509_get_subject_name is X509_get_subject_name, with the same arguments, return values and constants. Objects are passed around as plain integers (the C pointers) and freed explicitly, as in C. Most programs use it through IO::Socket::SSL or AnyEvent::TLS, which are built on it; use it directly for what they do not expose.

This is Net::SSLeay 1.96: all 709 functions and 769 constants of the CPAN distribution, and its Perl half (Net/SSLeay.pm, Net/SSLeay/Handle.pm) unchanged. Because each function is its C namesake, OpenSSL’s manual pages (man SSL_CTX_new) describe what it does; the overview below says where to look.

Requirements#

OpenSSL 3.0 or newer, as libssl.so.3 and libcrypto.so.3, loaded when the module is: nothing is linked into pperl. Without them, use Net::SSLeay dies naming the package to install. The module is part of the native-max build.

Synopsis#

A certificate’s subject, expiry and fingerprint - no network needed:

use Net::SSLeay;

my $bio  = Net::SSLeay::BIO_new_file('cert.pem', 'r') or die "cert.pem: $!";
my $x509 = Net::SSLeay::PEM_read_bio_X509($bio);
Net::SSLeay::BIO_free($bio);

print Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($x509)), "\n";
print Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509)), "\n";
print unpack('H*', Net::SSLeay::X509_digest($x509,
    Net::SSLeay::EVP_get_digestbyname('sha256'))), "\n";
Net::SSLeay::X509_free($x509);

A TLS client over a socket of your own:

use Socket;
use Net::SSLeay qw(die_now die_if_ssl_error);

my ($host, $port) = ('example.com', 443);
Net::SSLeay::initialize();
socket(my $sock, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "socket: $!";
connect($sock, sockaddr_in($port, inet_aton($host))) or die "connect: $!";

my $ctx = Net::SSLeay::CTX_new() or die_now("CTX_new: $!");
Net::SSLeay::CTX_set_options($ctx, Net::SSLeay::OP_ALL());
my $ssl = Net::SSLeay::new($ctx) or die_now("new: $!");
Net::SSLeay::set_tlsext_host_name($ssl, $host);    # SNI
Net::SSLeay::set_fd($ssl, fileno $sock);
Net::SSLeay::connect($ssl) == 1 or die_if_ssl_error('connect');
print 'cipher: ', Net::SSLeay::get_cipher($ssl), "\n";

Net::SSLeay::write($ssl, "GET / HTTP/1.0\r\nHost: $host\r\n\r\n");
my $reply = '';
while (defined(my $chunk = Net::SSLeay::read($ssl))) {
    last unless length $chunk;
    $reply .= $chunk;
}
Net::SSLeay::free($ssl);
Net::SSLeay::CTX_free($ctx);

This client does not verify the server’s certificate. To do so, before connect:

Net::SSLeay::CTX_set_default_verify_paths($ctx);   # the system's CAs
Net::SSLeay::set_verify($ssl, Net::SSLeay::VERIFY_PEER(), undef);
Net::SSLeay::X509_VERIFY_PARAM_set1_host(Net::SSLeay::get0_param($ssl), $host);

connect then fails for a certificate that does not chain to a trusted CA or does not name $host. IO::Socket::SSL does all of this by default.

The functions, by family#

The name says which C object a function works on; strip the prefix the C function had (SSL_, sometimes SSL_CTX_ becomes CTX_) and look it up in OpenSSL’s manual.

  • Contexts - CTX_* (112): CTX_new, the protocol versions, ciphers, certificates and keys a context offers, verification, sessions, and every callback (CTX_set_verify, CTX_set_alpn_select_cb, CTX_set_tlsext_servername_callback).

  • Connections - functions without a prefix: new, set_fd, connect, accept, read, write, shutdown, free, and the get_*/set_* accessors of a connection (get_peer_certificate, get_cipher, set_tlsext_host_name).

  • Sessions - SESSION_*, get_session, set_session.

  • Certificates - X509_* (162): names, extensions, stores and verification, CRLs, requests; P_X509_* are Net::SSLeay’s own helpers that return Perl lists (P_X509_get_crl_distribution_points, P_X509_get_ext_key_usage).

  • Keys and digests - EVP_*, RSA_*, EC_*, BN_*; RAND_* for random bytes.

  • Files and encodings - PEM_*, d2i_*/i2d_* (DER), BIO_* (memory and file buffers), ASN1_* and P_ASN1_* (times and integers).

  • Errors - ERR_get_error, ERR_error_string, and the module’s die_now, die_if_ssl_error and print_errs.

  • The rest - OCSP_*, OBJ_*, OSSL_PROVIDER_*, OPENSSL_* (version and initialisation).

Constants are functions too, named without their C prefix: Net::SSLeay::VERIFY_PEER(), Net::SSLeay::OP_ALL(), Net::SSLeay::ERROR_WANT_READ().

Written in Perl#

Net/SSLeay.pm adds whole-request helpers: get_https, post_https, sslcat, make_headers, make_form, and Net::SSLeay::Handle, a tied filehandle over a connection.

my ($page, $response, %headers) = Net::SSLeay::get_https('example.com', 443, '/');

Differences from upstream#

  • Which functions exist is decided by the OpenSSL loaded, not by the one the module was compiled against. Upstream compiles a function only for an OpenSSL that has its feature; here a function is defined only when the loaded library has every C function it needs - so defined &Net::SSLeay::client_hello_get_extension_order is false under OpenSSL 3.0 and 3.1, as it is for a Net::SSLeay built there (t/81-xs-native/Net-SSLeay/660-xsub-set-follows-openssl.t). On this machine’s OpenSSL it is upstream’s set of 709 (600-xsub-set.t).

  • The functions an OpenSSL can provide only when built with options off by default (MD2, SSLv3 methods) are not provided, whatever is loaded.

  • OpenSSL before 3.0 and LibreSSL are not supported; upstream builds against them too.

Modules#

  • Net::SSLeay::Handle - Perl module that lets SSL (HTTPS) sockets be handled as standard file handles.