[PATCH] AnyEvent::TLS and TLSv1.[12]

Maxime Soulé btik-cpan at scoubidou.com
Mon Sep 2 15:56:35 CEST 2013


Hello,

The new patch with documentation on openssl and Net::SSLeay needed 
versions...

Best regards,

Max.

Le 31.08.2013 10:00, Maxime Soulé a écrit :
> Hello,
>
> Le 30.08.2013 22:58, Marc Lehmann a écrit :
>> On Fri, Aug 30, 2013 at 04:36:07PM +0200, Maxime Soulé <btik-cpan at scoubidou.com> wrote:
>>> With the attached patch, it is now possible to handle specifically
>>> TLSv1.1 and TLSv1.2 protocols.
>> Looks good, except that these options require specific versions of
>> Net::SSLeay. Could you find out which version is required and add it to
>> the docs similar to e.g.t he check_crl option? I also wonder what could
>> be done if these protocols are requested but the underlying Net::SSLeay
>> or openssl don't support it - normally I'd do best effort, but with TLS,
>> that's not a good approach :)
> OK, I will do it and propose you that change.
>
> Net::SSLeay implements TLSv1_1 and TLSv1_2 from 1.55 and needs openssl
> 1.0.1 at least.
>
> If Net::SSLeay version is 1.55 and openssl version is less than 1.0.1, a
> runtime error occurs telling that Net::SSLeay can not autoload
> Net::SSLeay::CTX_tlsv1_1_new (for example).
>
>> Probably better, the code should be modified to die with an explanatory
>> message about Net::SSLeay or openssl being too old, depending on what
>> error message is currently generated.
> I will try to do something like this that will not obfuscate the
> existing code :)
>
>>> To avoid modifying AnyEvent::TLS each time a new protocol or option
>>> is available in Net::SSLeay, perhaps it could be a good thing to put
>>> the CTX creation and $op initialisation in a special class method, so
>>> we can inherit from AnyEvent::TLS and just redefine this method to
>>> add new options or new protocols?
>> You can already create and request the underlying ctx object so the first
>> is certainly possible until the underlying implementation changes, and I
>> don't know what "$op" is.
> Sorry, $op is the options passed to Net::SSLeay::CTX_set_options in new().
>
> I didn't see new_from_ssleay(), thanks. But it could be a good thing to
> initialize the CTX *and* to benefit from the CTX configuration you did
> in new() with various constructor options, to avoid to reinvent the
> wheel just to pass a "special" CTX.
>
> Perhaps doing the reverse I proposed above, creating a new (private)
> _init_instance() method that will be called in new() and
> new_from_ssleay() with their %args arguments? In this case
> new_from_ssleay() should accept additional arguments, in the same form
> as new(), but after the $ctx arg...
>
> Best regards,
>
> Max.

-------------- next part --------------
--- lib/AnyEvent/TLS.pm.orig	2013-08-30 15:47:20.000000000 +0200
+++ lib/AnyEvent/TLS.pm	2013-09-02 15:45:35.000000000 +0200
@@ -127,12 +127,13 @@
 
 =over 4
 
-=item method => "SSLv2" | "SSLv3" | "TLSv1" | "any"
+=item method => "SSLv2" | "SSLv3" | "TLSv1" | "TLSv1_1" | "TLSv1_2" | "any"
 
-The protocol parser to use. C<SSLv2>, C<SSLv3> and C<TLSv1> will use
-a parser for those protocols only (so will I<not> accept or create
-connections with/to other protocol versions), while C<any> (the
-default) uses a parser capable of all three protocols.
+The protocol parser to use. C<SSLv2>, C<SSLv3>, C<TLSv1>, C<TLSv1_1>
+and C<TLSv1_2> will use a parser for those protocols only (so will
+I<not> accept or create connections with/to other protocol versions),
+while C<any> (the default) uses a parser capable of all three
+protocols.
 
 The default is to use C<"any"> but disable SSLv2. This has the effect of
 sending a SSLv2 hello, indicating the support for SSLv3 and TLSv1, but not
@@ -141,11 +142,15 @@
 Specifying a specific version is almost always wrong to use for a server
 speaking to a wide variety of clients (e.g. web browsers), and often wrong
 for a client. If you only want to allow a specific protocol version, use
-the C<sslv2>, C<sslv3> or C<tlsv1> arguments instead.
+the C<sslv2>, C<sslv3>, C<tlsv1>, C<tlsv1_1> or C<tlsv1_2> arguments instead.
 
 For new services it is usually a good idea to enforce a C<TLSv1> method
 from the beginning.
 
+C<TLSv1_1> and C<TLSv1_2> require L<Net::SSLeay> >= 1.55 and OpenSSL
+>= 1.0.1. Check the L<Net::SSLeay> and OpenSSL documentations for more
+details.
+
 =item sslv2 => $enabled
 
 Enable or disable SSLv2 (normally I<disabled>).
@@ -158,6 +163,20 @@
 
 Enable or disable TLSv1 (normally I<enabled>).
 
+=item tlsv1_1 => $enabled
+
+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
@@ -553,6 +572,30 @@
 #   ocsp_request => 7,
 #);
 
+BEGIN {
+   eval 'sub _check_tls_gt_1 (){'
+      . (($Net::SSLeay::VERSION >= 1.55 && Net::SSLeay::OPENSSL_VERSION_NUMBER() >= 0x1000100f)*1)
+      . '}';
+}
+
+our %SSL_METHODS = (
+   any     => \&Net::SSLeay::CTX_new,
+   sslv23  => \&Net::SSLeay::CTX_new, # deliberately undocumented
+   sslv2   => \&Net::SSLeay::CTX_v2_new,
+   sslv3   => \&Net::SSLeay::CTX_v3_new,
+   tlsv1   => \&Net::SSLeay::CTX_tlsv1_new,
+);
+
+# Add TLSv1_1 and TLSv1_2 if Net::SSLEay and openssl allow them
+if (_check_tls_gt_1) {
+   $SSL_METHODS{tlsv1_1} = \&Net::SSLeay::CTX_tlsv1_1_new;
+   $SSL_METHODS{tlsv1_2} = \&Net::SSLeay::CTX_tlsv1_2_new;
+} else {
+   for my $method (qw(tlsv1_1 tlsv1_2)) {
+      $SSL_METHODS{$method} = sub { croak "AnyEvent::TLS method '$method' requires openssl v1.0.1 and Net::SSLeay 1.55 or higher" };
+   }
+}
+
 sub new {
    my ($class, %arg) = @_;
 
@@ -560,12 +603,8 @@
 
    my $method = lc $arg{method} || "any";
 
-   my $ctx = $method eq "any"    ? Net::SSLeay::CTX_new       ()
-           : $method eq "sslv23" ? Net::SSLeay::CTX_new       () # deliberately undocumented
-           : $method eq "sslv2"  ? Net::SSLeay::CTX_v2_new    ()
-           : $method eq "sslv3"  ? Net::SSLeay::CTX_v3_new    ()
-           : $method eq "tlsv1"  ? Net::SSLeay::CTX_tlsv1_new ()
-           : croak "'$method' is not a valid AnyEvent::TLS method (must be one of SSLv2, SSLv3, TLSv1 or any)";
+   my $ctx = ($SSL_METHODS{$method}
+              || croak "'$method' is not a valid AnyEvent::TLS method (must be one of @{[ sort keys %SSL_METHODS ]})")->();
 
    my $self = bless { ctx => $ctx }, $class; # to make sure it's destroyed if we croak
 
@@ -574,6 +613,8 @@
    $op |= Net::SSLeay::OP_NO_SSLv2      () unless $arg{sslv2};
    $op |= Net::SSLeay::OP_NO_SSLv3      () if exists $arg{sslv3} && !$arg{sslv3};
    $op |= Net::SSLeay::OP_NO_TLSv1      () if exists $arg{tlsv1} && !$arg{tlsv1};
+   $op |= Net::SSLeay::OP_NO_TLSv1_1    () if exists $arg{tlsv1_1} && !$arg{tlsv1_1} && _check_tls_gt_1;
+   $op |= Net::SSLeay::OP_NO_TLSv1_2    () if exists $arg{tlsv1_1} && !$arg{tlsv1_1} && _check_tls_gt_1;
    $op |= Net::SSLeay::OP_SINGLE_DH_USE () if !exists $arg{dh_single_use} || $arg{dh_single_use};
 
    Net::SSLeay::CTX_set_options ($ctx, $op);


More information about the anyevent mailing list