Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 Jun 2017 10:46:15 +0000 (UTC)
From:      Matthew Seaman <matthew@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-branches@freebsd.org
Subject:   svn commit: r443767 - in branches/2017Q2/www/rt44: . files
Message-ID:  <201706171046.v5HAkFcR002018@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: matthew
Date: Sat Jun 17 10:46:14 2017
New Revision: 443767
URL: https://svnweb.freebsd.org/changeset/ports/443767

Log:
  MFH: r443703
  
  Add security patches from BestPractical in lieu of the upcoming 4.4.2
  release.
  
  See: http://lists.bestpractical.com/pipermail/rt-announce/\
  2017-June/000297.html
  
  PR:		220031
  Approved by:	mikael.urankar@gmail.com (maintainer)
  Security:	7a92e958-5207-11e7-8d7c-6805ca0b3d42
  
  Approved by:	portmgr (miwi)

Added:
  branches/2017Q2/www/rt44/files/patch-lib_RT.pm
     - copied unchanged from r443703, head/www/rt44/files/patch-lib_RT.pm
  branches/2017Q2/www/rt44/files/patch-lib_RT_Authen_ExternalAuth_DBI.pm
     - copied unchanged from r443703, head/www/rt44/files/patch-lib_RT_Authen_ExternalAuth_DBI.pm
  branches/2017Q2/www/rt44/files/patch-lib_RT_Config.pm
     - copied unchanged from r443703, head/www/rt44/files/patch-lib_RT_Config.pm
  branches/2017Q2/www/rt44/files/patch-lib_RT_Interface_Web.pm
     - copied unchanged from r443703, head/www/rt44/files/patch-lib_RT_Interface_Web.pm
  branches/2017Q2/www/rt44/files/patch-lib_RT_User.pm
     - copied unchanged from r443703, head/www/rt44/files/patch-lib_RT_User.pm
  branches/2017Q2/www/rt44/files/patch-lib_RT_Util.pm
     - copied unchanged from r443703, head/www/rt44/files/patch-lib_RT_Util.pm
  branches/2017Q2/www/rt44/files/patch-sbin_rt-test-dependencies
     - copied unchanged from r443703, head/www/rt44/files/patch-sbin_rt-test-dependencies
  branches/2017Q2/www/rt44/files/patch-share_html_Dashboards_Subscription.html
     - copied unchanged from r443703, head/www/rt44/files/patch-share_html_Dashboards_Subscription.html
  branches/2017Q2/www/rt44/files/patch-share_html_Ticket_Attachment_dhandler
     - copied unchanged from r443703, head/www/rt44/files/patch-share_html_Ticket_Attachment_dhandler
Modified:
  branches/2017Q2/www/rt44/Makefile
  branches/2017Q2/www/rt44/files/patch-Makefile.in
  branches/2017Q2/www/rt44/files/patch-configure
Directory Properties:
  branches/2017Q2/   (props changed)

Modified: branches/2017Q2/www/rt44/Makefile
==============================================================================
--- branches/2017Q2/www/rt44/Makefile	Sat Jun 17 10:42:44 2017	(r443766)
+++ branches/2017Q2/www/rt44/Makefile	Sat Jun 17 10:46:14 2017	(r443767)
@@ -2,6 +2,7 @@
 
 PORTNAME=	rt
 DISTVERSION=	4.4.1
+PORTREVISION=	2
 CATEGORIES=	www
 MASTER_SITES=	http://download.bestpractical.com/pub/rt/release/
 PKGNAMESUFFIX=	44

Modified: branches/2017Q2/www/rt44/files/patch-Makefile.in
==============================================================================
--- branches/2017Q2/www/rt44/files/patch-Makefile.in	Sat Jun 17 10:42:44 2017	(r443766)
+++ branches/2017Q2/www/rt44/files/patch-Makefile.in	Sat Jun 17 10:46:14 2017	(r443767)
@@ -1,4 +1,4 @@
---- Makefile.in.orig	2016-07-18 UTC
+--- Makefile.in.orig	2016-07-18 20:20:17 UTC
 +++ Makefile.in
 @@ -59,7 +59,7 @@ RT_LAYOUT		=	@rt_layout_name@
  

Modified: branches/2017Q2/www/rt44/files/patch-configure
==============================================================================
--- branches/2017Q2/www/rt44/files/patch-configure	Sat Jun 17 10:42:44 2017	(r443766)
+++ branches/2017Q2/www/rt44/files/patch-configure	Sat Jun 17 10:46:14 2017	(r443767)
@@ -1,6 +1,6 @@
---- configure.orig	2014-09-11 19:03:07 UTC
+--- configure.orig	2016-07-20 15:48:58 UTC
 +++ configure
-@@ -2088,7 +2088,7 @@
+@@ -2112,7 +2112,7 @@ $as_echo "$as_me: WARNING: Layout file $
  		s/^#.*$//m;
  		s/^\s+//gim;
  		s/\s+$/\n/gim;

Copied: branches/2017Q2/www/rt44/files/patch-lib_RT.pm (from r443703, head/www/rt44/files/patch-lib_RT.pm)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2017Q2/www/rt44/files/patch-lib_RT.pm	Sat Jun 17 10:46:14 2017	(r443767, copy of r443703, head/www/rt44/files/patch-lib_RT.pm)
@@ -0,0 +1,13 @@
+--- lib/RT.pm.orig	2016-07-18 20:20:17 UTC
++++ 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();
+ 

Copied: branches/2017Q2/www/rt44/files/patch-lib_RT_Authen_ExternalAuth_DBI.pm (from r443703, head/www/rt44/files/patch-lib_RT_Authen_ExternalAuth_DBI.pm)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2017Q2/www/rt44/files/patch-lib_RT_Authen_ExternalAuth_DBI.pm	Sat Jun 17 10:46:14 2017	(r443767, copy of r443703, head/www/rt44/files/patch-lib_RT_Authen_ExternalAuth_DBI.pm)
@@ -0,0 +1,54 @@
+--- lib/RT/Authen/ExternalAuth/DBI.pm.orig	2016-07-18 20:20:17 UTC
++++ lib/RT/Authen/ExternalAuth/DBI.pm
+@@ -50,6 +50,7 @@ package RT::Authen::ExternalAuth::DBI;
+ 
+ use DBI;
+ use RT::Authen::ExternalAuth::DBI::Cookie;
++use RT::Util;
+ 
+ use warnings;
+ use strict;
+@@ -81,6 +82,7 @@ Provides the database implementation for
+             'p_field'                   =>  'password',
+ 
+             # Example of custom hashed password check
++            # (See below for security concerns with this implementation)
+             #'p_check'                   =>  sub {
+             #    my ($hash_from_db, $password) = @_;
+             #    return $hash_from_db eq function($password);
+@@ -170,6 +172,17 @@ An example, where C<FooBar()> is some ex
+ Importantly, the C<p_check> subroutine allows for arbitrarily complex password
+ checking unlike C<p_enc_pkg> and C<p_enc_sub>.
+ 
++Please note, the use of the C<eq> operator in the C<p_check> example above
++introduces a timing sidechannel vulnerability. (It was left there for clarity
++of the example.) There is a comparison function available in RT that is
++hardened against timing attacks. The comparison from the above example could
++be re-written with it like this:
++
++    p_check => sub {
++        my ($hash_from_db, $password) = @_;
++        return RT::Util::constant_time_eq($hash_from_db, FooBar($password));
++    },
++
+ =item p_enc_pkg, p_enc_sub
+ 
+ The Perl package and subroutine used to encrypt passwords from the
+@@ -298,7 +311,7 @@ sub GetAuth {
+         # Jump to the next external authentication service if they don't match
+         if(defined($db_p_salt)) {
+             $RT::Logger->debug("Using salt:",$db_p_salt);
+-            if(${encrypt}->($password,$db_p_salt) ne $pass_from_db){
++            unless (RT::Util::constant_time_eq(${encrypt}->($password,$db_p_salt), $pass_from_db)) {
+                 $RT::Logger->info(  $service,
+                                     "AUTH FAILED",
+                                     $username,
+@@ -306,7 +319,7 @@ sub GetAuth {
+                 return 0;
+             }
+         } else {
+-            if(${encrypt}->($password) ne $pass_from_db){
++            unless (RT::Util::constant_time_eq(${encrypt}->($password), $pass_from_db)) {
+                 $RT::Logger->info(  $service,
+                                     "AUTH FAILED",
+                                     $username,

Copied: branches/2017Q2/www/rt44/files/patch-lib_RT_Config.pm (from r443703, head/www/rt44/files/patch-lib_RT_Config.pm)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2017Q2/www/rt44/files/patch-lib_RT_Config.pm	Sat Jun 17 10:46:14 2017	(r443767, copy of r443703, head/www/rt44/files/patch-lib_RT_Config.pm)
@@ -0,0 +1,17 @@
+--- lib/RT/Config.pm.orig	2016-07-18 20:20:17 UTC
++++ lib/RT/Config.pm
+@@ -147,6 +147,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,

Copied: branches/2017Q2/www/rt44/files/patch-lib_RT_Interface_Web.pm (from r443703, head/www/rt44/files/patch-lib_RT_Interface_Web.pm)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2017Q2/www/rt44/files/patch-lib_RT_Interface_Web.pm	Sat Jun 17 10:46:14 2017	(r443767, copy of r443703, head/www/rt44/files/patch-lib_RT_Interface_Web.pm)
@@ -0,0 +1,20 @@
+--- lib/RT/Interface/Web.pm.orig	2016-07-18 20:20:17 UTC
++++ lib/RT/Interface/Web.pm
+@@ -1448,7 +1448,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});
+@@ -1666,7 +1666,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,
+     );

Copied: branches/2017Q2/www/rt44/files/patch-lib_RT_User.pm (from r443703, head/www/rt44/files/patch-lib_RT_User.pm)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2017Q2/www/rt44/files/patch-lib_RT_User.pm	Sat Jun 17 10:46:14 2017	(r443767, copy of r443703, head/www/rt44/files/patch-lib_RT_User.pm)
@@ -0,0 +1,87 @@
+--- lib/RT/User.pm.orig	2016-07-18 20:20:17 UTC
++++ 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 {
+     {
+@@ -1087,11 +1088,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;
+@@ -1101,16 +1108,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;
+@@ -1206,19 +1225,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

Copied: branches/2017Q2/www/rt44/files/patch-lib_RT_Util.pm (from r443703, head/www/rt44/files/patch-lib_RT_Util.pm)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2017Q2/www/rt44/files/patch-lib_RT_Util.pm	Sat Jun 17 10:46:14 2017	(r443767, copy of r443703, head/www/rt44/files/patch-lib_RT_Util.pm)
@@ -0,0 +1,70 @@
+--- lib/RT/Util.pm.orig	2016-07-18 20:20:17 UTC
++++ 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;

Copied: branches/2017Q2/www/rt44/files/patch-sbin_rt-test-dependencies (from r443703, head/www/rt44/files/patch-sbin_rt-test-dependencies)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2017Q2/www/rt44/files/patch-sbin_rt-test-dependencies	Sat Jun 17 10:46:14 2017	(r443767, copy of r443703, head/www/rt44/files/patch-sbin_rt-test-dependencies)
@@ -0,0 +1,11 @@
+--- sbin/rt-test-dependencies.orig	2016-07-20 15:49:00 UTC
++++ sbin/rt-test-dependencies
+@@ -136,7 +136,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

Copied: branches/2017Q2/www/rt44/files/patch-share_html_Dashboards_Subscription.html (from r443703, head/www/rt44/files/patch-share_html_Dashboards_Subscription.html)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2017Q2/www/rt44/files/patch-share_html_Dashboards_Subscription.html	Sat Jun 17 10:46:14 2017	(r443767, copy of r443703, head/www/rt44/files/patch-share_html_Dashboards_Subscription.html)
@@ -0,0 +1,11 @@
+--- share/html/Dashboards/Subscription.html.orig	2016-07-18 20:20:17 UTC
++++ 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>

Copied: branches/2017Q2/www/rt44/files/patch-share_html_Ticket_Attachment_dhandler (from r443703, head/www/rt44/files/patch-share_html_Ticket_Attachment_dhandler)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2017Q2/www/rt44/files/patch-share_html_Ticket_Attachment_dhandler	Sat Jun 17 10:46:14 2017	(r443767, copy of r443703, head/www/rt44/files/patch-share_html_Ticket_Attachment_dhandler)
@@ -0,0 +1,18 @@
+--- share/html/Ticket/Attachment/dhandler.orig	2016-07-18 20:20:17 UTC
++++ share/html/Ticket/Attachment/dhandler
+@@ -68,11 +68,13 @@ unless ( $AttachmentObj->TransactionId()
+ 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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706171046.v5HAkFcR002018>