commit 9a754ea2424f6f1c5e0acf0285b06ec9233ab5df Author: Arkadiusz Miśkiewicz <ar...@maven.pl> Date: Thu Jul 27 08:59:27 2017 +0200
- up to 4.2.14; fixes CVE-2017-5943, CVE-2016-6127, CVE-2015-7686, CVE-2017-5361, CVE-2017-5944 rt-4.2.13.patch | 263 -------------------------------------------------------- rt.spec | 10 +-- 2 files changed, 5 insertions(+), 268 deletions(-) --- diff --git a/rt.spec b/rt.spec index 4edfc18..1bc07d1 100644 --- a/rt.spec +++ b/rt.spec @@ -44,12 +44,12 @@ Summary: Request Tracker Summary(pl.UTF-8): Request Tracker - system do śledzenia zleceń Name: rt -Version: 4.2.13 -Release: 2 +Version: 4.2.14 +Release: 1 License: GPL v2 Group: Applications Source0: http://download.bestpractical.com/pub/rt/release/%{name}-%{version}.tar.gz -# Source0-md5: e48d3c5409d34b1413aa6348df8ca5d1 +# Source0-md5: 2bdb4bde3afe78356e0b3b864ffb9435 Source1: %{name}-apache_dir.conf Source2: %{name}-apache_vhost.conf Source3: %{name}-apache.conf @@ -57,7 +57,6 @@ Source4: %{name}.logrotate Source5: lighttpd.conf Patch0: %{name}-layout.patch Patch1: %{name}-config.patch -Patch2: rt-4.2.13.patch URL: http://www.bestpractical.com/rt/ BuildRequires: autoconf BuildRequires: automake @@ -155,6 +154,7 @@ BuildRequires: perl-Time-HiRes BuildRequires: perl-Time-modules BuildRequires: perl-TimeDate BuildRequires: perl-Tree-Simple >= %{perl_tree_simple_ver} +BuildRequires: perl-Type-Tiny BuildRequires: perl-UNIVERSAL-require BuildRequires: perl-WWW-Mechanize BuildRequires: perl-XML-RSS >= %{perl_xml_rss_ver} @@ -233,6 +233,7 @@ Requires: perl-Text-Password-Pronounceable Requires: perl-Text-Quoted >= %{perl_text_quoted_ver} Requires: perl-Text-WikiFormat >= %{perl_text_wikiformat_ver} Requires: perl-Tree-Simple >= %{perl_tree_simple_ver} +Requires: perl-Type-Tiny Requires: perl-UNIVERSAL-require Requires: perl-XML-RSS >= %{perl_xml_rss_ver} Requires: perl-base >= %{perl_ver} @@ -303,7 +304,6 @@ Pliki wspomagające używanie RT z Apache. %setup -q %patch0 -p0 %patch1 -p1 -%patch2 -p1 mv aclocal.m4 acinclude.m4 diff --git a/rt-4.2.13.patch b/rt-4.2.13.patch deleted file mode 100644 index 8184100..0000000 --- a/rt-4.2.13.patch +++ /dev/null @@ -1,263 +0,0 @@ -diff --git a/lib/RT.pm b/lib/RT.pm -index 743863d..b31fecb 100644 ---- a/lib/RT.pm -+++ b/lib/RT.pm -@@ -81,6 +81,10 @@ use vars qw($BasePath - $MasonDataDir - $MasonSessionDir); - -+# Set Email::Address module var before anything else loads. -+# This avoids an algorithmic complexity denial of service vulnerability. -+# See T#157608 and CVE-2015-7686 for more information. -+$Email::Address::COMMENT_NEST_LEVEL = 1; - - RT->LoadGeneratedData(); - -diff --git a/lib/RT/Config.pm b/lib/RT/Config.pm -index 2ec63f8..aa17587 100644 ---- a/lib/RT/Config.pm -+++ b/lib/RT/Config.pm -@@ -143,6 +143,14 @@ can be set for each config optin: - our %META; - %META = ( - # General user overridable options -+ RestrictReferrerLogin => { -+ PostLoadCheck => sub { -+ my $self = shift; -+ if (defined($self->Get('RestrictReferrerLogin'))) { -+ RT::Logger->error("The config option 'RestrictReferrerLogin' is incorrect, and should be 'RestrictLoginReferrer' instead."); -+ } -+ }, -+ }, - DefaultQueue => { - Section => 'General', - Overridable => 1, -diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm -index cbf10d2..d915279 100644 ---- a/lib/RT/Interface/Web.pm -+++ b/lib/RT/Interface/Web.pm -@@ -1426,7 +1426,7 @@ sub IsCompCSRFWhitelisted { - # golden. This acts on the presumption that external forms may - # hardcode a username and password -- if a malicious attacker knew - # both already, CSRF is the least of your problems. -- my $AllowLoginCSRF = not RT->Config->Get('RestrictReferrerLogin'); -+ my $AllowLoginCSRF = not RT->Config->Get('RestrictLoginReferrer'); - if ($AllowLoginCSRF and defined($args{user}) and defined($args{pass})) { - my $user_obj = RT::CurrentUser->new(); - $user_obj->Load($args{user}); -@@ -1642,7 +1642,7 @@ sub MaybeShowInterstitialCSRFPage { - my $token = StoreRequestToken($ARGS); - $HTML::Mason::Commands::m->comp( - '/Elements/CSRF', -- OriginalURL => RT->Config->Get('WebPath') . $HTML::Mason::Commands::r->path_info, -+ OriginalURL => RT->Config->Get('WebBaseURL') . RT->Config->Get('WebPath') . $HTML::Mason::Commands::r->path_info, - Reason => HTML::Mason::Commands::loc( $msg, @loc ), - Token => $token, - ); -diff --git a/lib/RT/User.pm b/lib/RT/User.pm -index 39b8197..28098bc 100644 ---- a/lib/RT/User.pm -+++ b/lib/RT/User.pm -@@ -84,6 +84,7 @@ use RT::Principals; - use RT::ACE; - use RT::Interface::Email; - use Text::Password::Pronounceable; -+use RT::Util; - - sub _OverlayAccessible { - { -@@ -977,11 +978,17 @@ sub IsPassword { - # If it's a new-style (>= RT 4.0) password, it starts with a '!' - my (undef, $method, @rest) = split /!/, $stored; - if ($method eq "bcrypt") { -- return 0 unless $self->_GeneratePassword_bcrypt($value, @rest) eq $stored; -+ return 0 unless RT::Util::constant_time_eq( -+ $self->_GeneratePassword_bcrypt($value, @rest), -+ $stored -+ ); - # Upgrade to a larger number of rounds if necessary - return 1 unless $rest[0] < RT->Config->Get('BcryptCost'); - } elsif ($method eq "sha512") { -- return 0 unless $self->_GeneratePassword_sha512($value, @rest) eq $stored; -+ return 0 unless RT::Util::constant_time_eq( -+ $self->_GeneratePassword_sha512($value, @rest), -+ $stored -+ ); - } else { - $RT::Logger->warn("Unknown hash method $method"); - return 0; -@@ -991,16 +998,28 @@ sub IsPassword { - my $hash = MIME::Base64::decode_base64($stored); - # Decoding yields 30 byes; first 4 are the salt, the rest are substr(SHA256,0,26) - my $salt = substr($hash, 0, 4, ""); -- return 0 unless substr(Digest::SHA::sha256($salt . Digest::MD5::md5(Encode::encode( "UTF-8", $value))), 0, 26) eq $hash; -+ return 0 unless RT::Util::constant_time_eq( -+ substr(Digest::SHA::sha256($salt . Digest::MD5::md5(Encode::encode( "UTF-8", $value))), 0, 26), -+ $hash -+ ); - } elsif (length $stored == 32) { - # Hex nonsalted-md5 -- return 0 unless Digest::MD5::md5_hex(Encode::encode( "UTF-8", $value)) eq $stored; -+ return 0 unless RT::Util::constant_time_eq( -+ Digest::MD5::md5_hex(Encode::encode( "UTF-8", $value)), -+ $stored -+ ); - } elsif (length $stored == 22) { - # Base64 nonsalted-md5 -- return 0 unless Digest::MD5::md5_base64(Encode::encode( "UTF-8", $value)) eq $stored; -+ return 0 unless RT::Util::constant_time_eq( -+ Digest::MD5::md5_base64(Encode::encode( "UTF-8", $value)), -+ $stored -+ ); - } elsif (length $stored == 13) { - # crypt() output -- return 0 unless crypt(Encode::encode( "UTF-8", $value), $stored) eq $stored; -+ return 0 unless RT::Util::constant_time_eq( -+ crypt(Encode::encode( "UTF-8", $value), $stored), -+ $stored -+ ); - } else { - $RT::Logger->warning("Unknown password form"); - return 0; -@@ -1096,19 +1115,20 @@ sub GenerateAuthString { - - =head3 ValidateAuthString - --Takes auth string and protected string. Returns true is protected string -+Takes auth string and protected string. Returns true if protected string - has been protected by user's L</AuthToken>. See also L</GenerateAuthString>. - - =cut - - sub ValidateAuthString { - my $self = shift; -- my $auth_string = shift; -+ my $auth_string_to_validate = shift; - my $protected = shift; - - my $str = Encode::encode( "UTF-8", $self->AuthToken . $protected ); -+ my $valid_auth_string = substr(Digest::MD5::md5_hex($str),0,16); - -- return $auth_string eq substr(Digest::MD5::md5_hex($str),0,16); -+ return RT::Util::constant_time_eq( $auth_string_to_validate, $valid_auth_string ); - } - - =head2 SetDisabled -diff --git a/lib/RT/Util.pm b/lib/RT/Util.pm -index 70b557b..47b1dd2 100644 ---- a/lib/RT/Util.pm -+++ b/lib/RT/Util.pm -@@ -54,6 +54,8 @@ use warnings; - use base 'Exporter'; - our @EXPORT = qw/safe_run_child mime_recommended_filename/; - -+use Encode qw/encode/; -+ - sub safe_run_child (&) { - my $our_pid = $$; - -@@ -150,6 +152,58 @@ sub assert_bytes { - } - - -+=head2 C<constant_time_eq($a, $b)> -+ -+Compares two strings for equality in constant-time. Replacement for the C<eq> -+operator designed to avoid timing side-channel vulnerabilities. Returns zero -+or one. -+ -+This is intended for use in cryptographic subsystems for comparing well-formed -+data such as hashes - not for direct use with user input or as a general -+replacement for the C<eq> operator. -+ -+The two string arguments B<MUST> be of equal length. If the lengths differ, -+this function will call C<die()>, as proceeding with execution would create -+a timing vulnerability. Length is defined by characters, not bytes. -+ -+This code has been tested to do what it claims. Do not change it without -+thorough statistical timing analysis to validate the changes. -+ -+Added to resolve CVE-2017-5361 -+ -+For more on timing attacks, see this Wikipedia article: -+B<https://en.wikipedia.org/wiki/Timing_attack> -+ -+=cut -+ -+sub constant_time_eq { -+ my ($a, $b) = @_; -+ -+ my $result = 0; -+ -+ # generic error message avoids potential information leaks -+ my $generic_error = "Cannot compare values"; -+ die $generic_error unless defined $a and defined $b; -+ die $generic_error unless length $a == length $b; -+ die $generic_error if ref($a) or ref($b); -+ -+ for (my $i = 0; $i < length($a); $i++) { -+ my $a_char = substr($a, $i, 1); -+ my $b_char = substr($b, $i, 1); -+ -+ # encode() is set to die on malformed -+ my @a_octets = unpack("C*", encode('UTF-8', $a_char, Encode::FB_CROAK)); -+ my @b_octets = unpack("C*", encode('UTF-8', $b_char, Encode::FB_CROAK)); -+ die $generic_error if (scalar @a_octets) != (scalar @b_octets); -+ -+ for (my $j = 0; $j < scalar @a_octets; $j++) { -+ $result |= $a_octets[$j] ^ $b_octets[$j]; -+ } -+ } -+ return 0 + not $result; -+} -+ -+ - RT::Base->_ImportOverlays(); - - 1; -diff --git a/sbin/rt-test-dependencies b/sbin/rt-test-dependencies -index ef5dc09..9e047d8 100644 ---- a/sbin/rt-test-dependencies -+++ b/sbin/rt-test-dependencies -@@ -206,7 +206,7 @@ Devel::StackTrace 1.19 - Digest::base - Digest::MD5 2.27 - Digest::SHA --Email::Address 1.897 -+Email::Address 1.908 - Email::Address::List 0.02 - Encode 2.64 - Errno -diff --git a/share/html/Dashboards/Subscription.html b/share/html/Dashboards/Subscription.html -index 83680ef..d98d020 100644 ---- a/share/html/Dashboards/Subscription.html -+++ b/share/html/Dashboards/Subscription.html -@@ -75,7 +75,7 @@ - <ol class="dashboard-queries"> - % for my $portlet (@portlets) { - <li class="dashboard-query"> -- <% loc($portlet->{description}, $fields{'Rows'}) %> -+ <% loc( RT::SavedSearch->EscapeDescription($portlet->{description}), $fields{'Rows'}) %> - </li> - % } - </ol> -diff --git a/share/html/Ticket/Attachment/dhandler b/share/html/Ticket/Attachment/dhandler -index 3d7c07b..c6ca376 100644 ---- a/share/html/Ticket/Attachment/dhandler -+++ b/share/html/Ticket/Attachment/dhandler -@@ -68,11 +68,13 @@ unless ( $AttachmentObj->TransactionId() == $trans ) { - my $content = $AttachmentObj->OriginalContent; - my $content_type = $AttachmentObj->ContentType || 'text/plain'; - --if ( RT->Config->Get('AlwaysDownloadAttachments') ) { -+my $attachment_regex = qr{^(image/svg\+xml|application/pdf)}i; -+if ( RT->Config->Get('AlwaysDownloadAttachments') || ($content_type =~ $attachment_regex) ) { - $r->headers_out->{'Content-Disposition'} = "attachment"; - } - elsif ( !RT->Config->Get('TrustHTMLAttachments') ) { -- $content_type = 'text/plain' if ( $content_type =~ /^text\/html/i ); -+ my $text_plain_regex = qr{^(text/html|application/xhtml\+xml|text/xml|application/xml)}i; -+ $content_type = 'text/plain' if ( $content_type =~ $text_plain_regex ); - } - elsif (lc $content_type eq 'text/html') { - # If we're trusting and serving HTML for display not download, try to do ================================================================ ---- gitweb: http://git.pld-linux.org/gitweb.cgi/packages/rt.git/commitdiff/9a754ea2424f6f1c5e0acf0285b06ec9233ab5df _______________________________________________ pld-cvs-commit mailing list pld-cvs-commit@lists.pld-linux.org http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit