From 3634ba4ffddaf9fa3fd01e9dcc3f701ae32dcf20 Mon Sep 17 00:00:00 2001 From: Marcel Denia Date: Mon, 11 Aug 2014 17:18:04 +0200 Subject: [PATCH] perl-www: Default to verifying hostnames when using SSL This is a backport of perl-www 6.00's CVE-2011-0633 fix. Signed-off-by: Marcel Denia --- ...ttps-call-verify-hostname-when-avail.patch | 41 +++++++ ...wp-https-verify-hostnames-by-default.patch | 113 ++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 lang/perl-www/patches/010-lwp-https-call-verify-hostname-when-avail.patch create mode 100644 lang/perl-www/patches/020-lwp-https-verify-hostnames-by-default.patch diff --git a/lang/perl-www/patches/010-lwp-https-call-verify-hostname-when-avail.patch b/lang/perl-www/patches/010-lwp-https-call-verify-hostname-when-avail.patch new file mode 100644 index 0000000000..9166e891e5 --- /dev/null +++ b/lang/perl-www/patches/010-lwp-https-call-verify-hostname-when-avail.patch @@ -0,0 +1,41 @@ +commit 3b266f17ccd5613a9c42d1e04118e94ca6467489 +Author: Gisle Aas +Date: Sun Jan 16 12:56:30 2011 +0100 + + Call IO::Socket::SSL's verify_hostname when available + +--- a/lib/LWP/Protocol/https.pm ++++ b/lib/LWP/Protocol/https.pm +@@ -14,6 +14,15 @@ sub socket_type + sub _check_sock + { + my($self, $req, $sock) = @_; ++ if ($sock->can("verify_hostname")) { ++ if (!$sock->verify_hostname($req->uri->host, "www")) { ++ my $subject = $sock->peer_certificate("subject"); ++ die "SSL-peer fails verification [subject=$subject]\n"; ++ } ++ else { ++ $req->{ssl_sock_verified}++; ++ } ++ } + my $check = $req->header("If-SSL-Cert-Subject"); + if (defined $check) { + my $cert = $sock->get_peer_certificate || +@@ -36,9 +45,14 @@ sub _get_sock_info + $res->header("Client-SSL-Cert-Subject" => $cert->subject_name); + $res->header("Client-SSL-Cert-Issuer" => $cert->issuer_name); + } +- if(! eval { $sock->get_peer_verify }) { +- $res->header("Client-SSL-Warning" => "Peer certificate not verified"); ++ if (!$res->request->{ssl_sock_verified}) { ++ if(! eval { $sock->get_peer_verify }) { ++ my $msg = "Peer certificate not verified"; ++ $msg .= " [$@]" if $@; ++ $res->header("Client-SSL-Warning" => $msg); ++ } + } ++ $res->header("Client-SSL-Socket-Class" => $Net::HTTPS::SSL_SOCKET_CLASS); + } + + #----------------------------------------------------------- diff --git a/lang/perl-www/patches/020-lwp-https-verify-hostnames-by-default.patch b/lang/perl-www/patches/020-lwp-https-verify-hostnames-by-default.patch new file mode 100644 index 0000000000..465010e2b2 --- /dev/null +++ b/lang/perl-www/patches/020-lwp-https-verify-hostnames-by-default.patch @@ -0,0 +1,113 @@ +commit 62dd58188d8f8987d24bd84951813a54a8bf5987 +Author: Gisle Aas +Date: Mon Jan 24 23:19:59 2011 +0100 + + Default to verifying hostnames when using SSL + +--- a/lib/LWP/Protocol/https.pm ++++ b/lib/LWP/Protocol/https.pm +@@ -11,18 +11,30 @@ sub socket_type + return "https"; + } + +-sub _check_sock ++sub _extra_sock_opts + { +- my($self, $req, $sock) = @_; +- if ($sock->can("verify_hostname")) { +- if (!$sock->verify_hostname($req->uri->host, "www")) { +- my $subject = $sock->peer_certificate("subject"); +- die "SSL-peer fails verification [subject=$subject]\n"; +- } +- else { +- $req->{ssl_sock_verified}++; ++ my $self = shift; ++ my %ssl_opts = %{$self->{ua}{ssl_opts} || {}}; ++ unless (exists $ssl_opts{SSL_verify_mode}) { ++ $ssl_opts{SSL_verify_mode} = 1; ++ } ++ if (delete $ssl_opts{verify_hostname}) { ++ $ssl_opts{SSL_verify_mode} ||= 1; ++ $ssl_opts{SSL_verifycn_scheme} = 'www'; ++ } ++ if ($ssl_opts{SSL_verify_mode}) { ++ unless (exists $ssl_opts{SSL_ca_file} || exists $ssl_opts{SSL_ca_path}) { ++ require Mozilla::CA; ++ $ssl_opts{SSL_ca_file} = Mozilla::CA::SSL_ca_file(); + } + } ++ $self->{ssl_opts} = \%ssl_opts; ++ return (%ssl_opts, $self->SUPER::_extra_sock_opts); ++} ++ ++sub _check_sock ++{ ++ my($self, $req, $sock) = @_; + my $check = $req->header("If-SSL-Cert-Subject"); + if (defined $check) { + my $cert = $sock->get_peer_certificate || +@@ -45,12 +57,11 @@ sub _get_sock_info + $res->header("Client-SSL-Cert-Subject" => $cert->subject_name); + $res->header("Client-SSL-Cert-Issuer" => $cert->issuer_name); + } +- if (!$res->request->{ssl_sock_verified}) { +- if(! eval { $sock->get_peer_verify }) { +- my $msg = "Peer certificate not verified"; +- $msg .= " [$@]" if $@; +- $res->header("Client-SSL-Warning" => $msg); +- } ++ if (!$self->{ssl_opts}{SSL_verify_mode}) { ++ $res->push_header("Client-SSL-Warning" => "Peer certificate not verified"); ++ } ++ elsif (!$self->{ssl_opts}{SSL_verifycn_scheme}) { ++ $res->push_header("Client-SSL-Warning" => "Peer hostname match with certificate not verified"); + } + $res->header("Client-SSL-Socket-Class" => $Net::HTTPS::SSL_SOCKET_CLASS); + } +--- a/lib/LWP/UserAgent.pm ++++ b/lib/LWP/UserAgent.pm +@@ -41,6 +41,7 @@ sub new + my $timeout = delete $cnf{timeout}; + $timeout = 3*60 unless defined $timeout; + my $local_address = delete $cnf{local_address}; ++ my $ssl_opts = delete $cnf{ssl_opts}; + my $use_eval = delete $cnf{use_eval}; + $use_eval = 1 unless defined $use_eval; + my $parse_head = delete $cnf{parse_head}; +@@ -83,6 +84,7 @@ sub new + def_headers => $def_headers, + timeout => $timeout, + local_address => $local_address, ++ ssl_opts => { $ssl_opts ? %$ssl_opts : (verify_hostname => 1) }, + use_eval => $use_eval, + show_progress=> $show_progress, + max_size => $max_size, +@@ -582,6 +584,20 @@ sub max_size { shift->_elem('max_siz + sub max_redirect { shift->_elem('max_redirect', @_); } + sub show_progress{ shift->_elem('show_progress', @_); } + ++sub ssl_opts { ++ my $self = shift; ++ if (@_ == 1) { ++ my $k = shift; ++ return $self->{ssl_opts}{$k}; ++ } ++ if (@_) { ++ %{$self->{ssl_opts}} = (%{$self->{ssl_opts}}, @_); ++ } ++ else { ++ return keys %{$self->{ssl_opts}}; ++ } ++} ++ + sub parse_head { + my $self = shift; + if (@_) { +@@ -1040,6 +1056,7 @@ The following options correspond to attr + cookie_jar undef + default_headers HTTP::Headers->new + local_address undef ++ ssl_opts { verify_hostname => 1 } + max_size undef + max_redirect 7 + parse_head 1