From fdf9d5882c402b299e087a4d71efb8c9838517ab Mon Sep 17 00:00:00 2001 From: matthew Date: Sat, 17 Jun 2017 10:46:14 +0000 Subject: 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) --- www/rt44/files/patch-lib_RT_User.pm | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 www/rt44/files/patch-lib_RT_User.pm (limited to 'www/rt44/files/patch-lib_RT_User.pm') diff --git a/www/rt44/files/patch-lib_RT_User.pm b/www/rt44/files/patch-lib_RT_User.pm new file mode 100644 index 0000000..baa70db --- /dev/null +++ b/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. See also L. + + =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 -- cgit v1.1