AnyEvent

 view release on metacpan or  search on metacpan

lib/AnyEvent/TLS.pm  view on Meta::CPAN

Enable or disable TLSv1_1 (normally I<enabled>).

This requires L<Net::SSLeay> >= 1.55 and OpenSSL >= 1.0.1. Check the
L<Net::SSLeay> and OpenSSL documentations for more details.

=item tlsv1_2 => $enabled

Enable or disable TLSv1_2 (normally I<enabled>).

This requires L<Net::SSLeay> >= 1.55 and OpenSSL >= 1.0.1. Check the
L<Net::SSLeay> and OpenSSL documentations for more details.

=item verify => $enable

Enable or disable peer certificate checking (default is I<disabled>, which
is I<not recommended>).

This is the "master switch" for all verify-related parameters and
functions.

If it is disabled, then no peer certificate verification will be done
- the connection will be encrypted, but the peer certificate won't be
verified against any known CAs, or whether it is still valid or not. No
peername verification or custom verification will be done either.

If enabled, then the peer certificate (required in client mode, optional
in server mode, see C<verify_require_client_cert>) will be checked against
its CA certificate chain - that means there must be a signing chain from
the peer certificate to any of the CA certificates you trust locally, as
specified by the C<ca_file> and/or C<ca_path> and/or C<ca_cert> parameters
(or the system default CA repository, if all of those parameters are
missing - see also the L<AnyEvent> manpage for the description of
PERL_ANYEVENT_CA_FILE).

Other basic checks, such as checking the validity period, will also be
done, as well as optional peername/hostname/common name verification
C<verify_peername>.

An optional C<verify_cb> callback can also be set, which will be invoked
with the verification results, and which can override the decision.

=item verify_require_client_cert => $enable

Enable or disable mandatory client certificates (default is
I<disabled>). When this mode is enabled, then a client certificate will be
required in server mode (a server certificate is mandatory, so in client
mode, this switch has no effect).

=item verify_peername => $scheme | $callback->($tls, $cert, $peername)

TLS only protects the data that is sent - it cannot automatically verify
that you are really talking to the right peer. The reason is that
certificates contain a "common name" (and a set of possible alternative
"names") that need to be checked against the peername (usually, but not
always, the DNS name of the server) in a protocol-dependent way.

This can be implemented by specifying a callback that has to verify that
the actual C<$peername> matches the given certificate in C<$cert>.

Since this can be rather hard to implement, AnyEvent::TLS offers a variety
of predefined "schemes" (lifted from L<IO::Socket::SSL>) that are named
like the protocols that use them:

=over 4

=item ldap (rfc4513), pop3,imap,acap (rfc2995), nntp (rfc4642)

Simple wildcards in subjectAltNames are possible, e.g. *.example.org
matches www.example.org but not lala.www.example.org. If nothing from
subjectAltNames matches, it checks against the common name, but there are
no wildcards allowed.

=item http (rfc2818)

Extended wildcards in subjectAltNames are possible, e.g. *.example.org or
even www*.example.org. Wildcards in the common name are not allowed. The
common name will be only checked if no host names are given in
subjectAltNames.

=item smtp (rfc3207)

This RFC isn't very useful in determining how to do verification so it
just assumes that subjectAltNames are possible, but no wildcards are
possible anywhere.

=item [$wildcards_in_alt, $wildcards_in_cn, $check_cn]

You can also specify a scheme yourself by using an array reference with
three integers.

C<$wildcards_in_alt> and C<$wildcards_in_cn> specify whether and where
wildcards (C<*>) are allowed in subjectAltNames and the common name,
respectively. C<0> means no wildcards are allowed, C<1> means they
are allowed only as the first component (C<*.example.org>), and C<2>
means they can be used anywhere (C<www*.example.org>), except that very
dangerous matches will not be allowed (C<*.org> or C<*>).

C<$check_cn> specifies if and how the common name field is checked: C<0>
means it will be completely ignored, C<1> means it will only be used if
no host names have been found in the subjectAltNames, and C<2> means the
common name will always be checked against the peername.

=back

You can specify either the name of the parent protocol (recommended,
e.g. C<http>, C<ldap>), the protocol name as usually used in URIs
(e.g. C<https>, C<ldaps>) or the RFC (not recommended, e.g. C<rfc2995>,
C<rfc3920>).

This verification will only be done when verification is enabled (C<<
verify => 1 >>).

=item verify_cb => $callback->($tls, $ref, $cn, $depth, $preverify_ok, $x509_store_ctx, $cert)

Provide a custom peer verification callback used by TLS sessions,
which is called with the result of any other verification (C<verify>,
C<verify_peername>).

This callback will only be called when verification is enabled (C<< verify
=> 1 >>).

lib/AnyEvent/TLS.pm  view on Meta::CPAN

   Net::SSLeay::free ($session);
}

#sub _ref($) {
#   $REF_MAP{Net::SSLeay::get_ex_data ($_[0], $REF_IDX)}
#}

sub DESTROY {
   my ($self) = @_;

   # better be safe than sorry with net-ssleay
   Net::SSLeay::CTX_set_default_passwd_cb ($self->{ctx});

   Net::SSLeay::CTX_free ($self->{ctx});
}

=item AnyEvent::TLS::init

AnyEvent::TLS does on-demand initialisation, and normally there is no need to call an initialise
function.

As initialisation might take some time (to read e.g. C</dev/urandom>), this
could be annoying in some highly interactive programs. In that case, you can
call C<AnyEvent::TLS::init> to make sure there will be no costly initialisation
later. It is harmless to call C<AnyEvent::TLS::init> multiple times.

=cut

sub init() {
   return if $REF_IDX;

   AE::log 5 => "Net::SSLeay versions older than 1.33 might malfunction."
      if $Net::SSLeay::VERSION < 1.33;

   Net::SSLeay::load_error_strings ();
   Net::SSLeay::SSLeay_add_ssl_algorithms ();
   Net::SSLeay::randomize ();

   $REF_IDX = Net::SSLeay::get_ex_new_index (0, 0, 0, 0, 0)
      until $REF_IDX; # Net::SSLeay uses id #0 for its own stuff without allocating it
}

=item $certname = AnyEvent::TLS::certname $x509

Utility function that returns a user-readable string identifying the X509
certificate object.

=cut

sub certname {
   $_[0]
      ? Net::SSLeay::X509_NAME_oneline (Net::SSLeay::X509_get_issuer_name ($_[0]))
        . Net::SSLeay::X509_NAME_oneline (Net::SSLeay::X509_get_subject_name ($_[0]))
      : undef
}

our %CN_SCHEME = (
   # each tuple is [$cn_wildcards, $alt_wildcards, $check_cn]
   # where *_wildcards is 0 for none allowed, 1 for allowed at beginning and 2 for allowed everywhere
   # and check_cn is 0 for do not check, 1 for check when no alternate dns names and 2 always
   # all of this is from IO::Socket::SSL

   rfc4513 => [0, 1, 2],
   rfc2818 => [0, 2, 1],
   rfc3207 => [0, 0, 2], # see IO::Socket::SSL, rfc seems unclear
   none    => [],        # do not check

   ldap    => "rfc4513",                    ldaps => "ldap",
   http    => "rfc2818",                    https => "http",
   smtp    => "rfc3207",                    smtps => "smtp",

   xmpp    => "rfc3920", rfc3920 => "http",
   pop3    => "rfc2595", rfc2595 => "ldap", pop3s => "pop3",
   imap    => "rfc2595", rfc2595 => "ldap", imaps => "imap",
   acap    => "rfc2595", rfc2595 => "ldap",
   nntp    => "rfc4642", rfc4642 => "ldap", nntps => "nntp",
   ftp     => "rfc4217", rfc4217 => "http", ftps  => "ftp" ,
);

sub match_cn($$$) {
   my ($name, $cn, $type) = @_;

   # remove leading and trailing garbage
   for ($name, $cn) {
      s/[\x00-\x1f]+$//;
      s/^[\x00-\x1f]+//;
   }

   my $pattern;

   ### IMPORTANT!
   # we accept only a single wildcard and only for a single part of the FQDN
   # e.g *.example.org does match www.example.org but not bla.www.example.org
   # The RFCs are in this regard unspecific but we don't want to have to
   # deal with certificates like *.com, *.co.uk or even *
   # see also http://nils.toedtmann.net/pub/subjectAltName.txt
   if ($type == 2 and $name =~m{^([^.]*)\*(.+)} ) {
      $pattern = qr{^\Q$1\E[^.]*\Q$2\E$}i;
   } elsif ($type == 1 and $name =~m{^\*(\..+)$} ) {
      $pattern = qr{^[^.]*\Q$1\E$}i;
   } else {
      $pattern = qr{^\Q$name\E$}i;
   }

   $cn =~ $pattern
}

# taken verbatim from IO::Socket::SSL, then changed to take advantage of
# AnyEvent utilities.
sub verify_hostname($$$) {
   my ($cn, $cert, $scheme) = @_;

   while (!ref $scheme) {
      $scheme = $CN_SCHEME{$scheme}
         or return 1;
   }

   my $cert_cn =
      Net::SSLeay::X509_NAME_get_text_by_NID (
         Net::SSLeay::X509_get_subject_name ($cert), Net::SSLeay::NID_commonName ());

   my @cert_alt = Net::SSLeay::X509_get_subjectAltNames ($cert);

   # rfc2460 - convert to network byte order
   require AnyEvent::Socket;
   my $ip = AnyEvent::Socket::parse_address ($cn);

   my $alt_dns_count;

   while (my ($type, $name) = splice @cert_alt, 0, 2) {
      if ($type == Net::SSLeay::GEN_IPADD ()) {
         # $name is already packed format (inet_xton)
         return 1 if $ip eq $name;
      } elsif ($type == Net::SSLeay::GEN_DNS ()) {
         $alt_dns_count++;

         return 1 if match_cn $name, $cn, $scheme->[1];
      }
   }

   if ($scheme->[2] == 2
       || ($scheme->[2] == 1 && !$alt_dns_count)) {
      return 1 if match_cn $cert_cn, $cn, $scheme->[0];
   }

   0
}

=back

=head1 SSL/TLS QUICK FACTS

Here are some quick facts about TLS/SSL that might help you:

=over 4

=item * A certificate is the public key part, a key is the private key part.

While not strictly true, certificates are the things you can hand around
publicly as a kind of identity, while keys should really be kept private,
as proving that you have the private key is usually interpreted as being
the entity behind the certificate.

=item * A certificate is signed by a CA (Certificate Authority).

By signing, the CA basically claims that the certificate it signs
really belongs to the identity named in it, verified according to the
CA policies. For e.g. HTTPS, the CA usually makes some checks that the

lib/AnyEvent/TLS.pm  view on Meta::CPAN

So peername verification is almost as important as checking the CA
signing. Unfortunately, every protocol implements this differently, if at
all...

=item * Switching off verification is sometimes reasonable.

You can switch off verification. You still get an encrypted connection
that is protected against eavesdropping and injection - you just lose
protection against man in the middle attacks, i.e. somebody else with
enough abilities to intercept all traffic can masquerade herself as the
other side.

For many applications, switching off verification is entirely
reasonable. Downloading random stuff from websites using HTTPS for no
reason is such an application. Talking to your bank and entering TANs is
not such an application.

=item * A SSL/TLS server always needs a certificate/key pair to operate,
for clients this is optional.

Apart from (usually disabled) anonymous cipher suites, a server always
needs a certificate/key pair to operate.

Clients almost never use certificates, but if they do, they can be used
to authenticate the client, just as server certificates can be used to
authenticate the server.

=item * SSL version 2 is very insecure.

SSL version 2 is old and not only has it some security issues, SSLv2-only
implementations are usually buggy, too, due to their age.

=item * Sometimes, even losing your "private" key might not expose all your
data.

With Diffie-Hellman ephemeral key exchange, you can lose the DH parameters
(the "keys"), but all your connections are still protected. Diffie-Hellman
needs special set-up (done by default by AnyEvent::TLS).

=back

=head1 SECURITY CONSIDERATIONS

When you use any of the options that pass in keys or certificates
as strings (e.g. C<ca_cert>), then, due to serious shortcomings in
L<Net::SSLeay>, this module creates a temporary file to store the string -
see L<File::Temp> and possibly its C<safe_level> setting for more details
on what to watch out for.

=head1 BUGS

Due to the abysmal code quality of Net::SSLeay, this module will leak small
amounts of memory per TLS connection (currently at least one perl scalar).

=head1 AUTHORS

Marc Lehmann <schmorp@schmorp.de>.

Some of the API, documentation and implementation (verify_hostname),
and a lot of ideas/workarounds/knowledge have been taken from the
L<IO::Socket::SSL> module. Care has been taken to keep the API similar to
that and other modules, to the extent possible while providing a sensible
API for AnyEvent.

=cut

1



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