View | Details | Raw Unified | Return to bug 18298
Collapse All | Expand All

(-)a/Koha/AuthUtils.pm (+48 lines)
Lines 22-27 use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64); Link Here
22
use Encode qw( encode is_utf8 );
22
use Encode qw( encode is_utf8 );
23
use Fcntl qw/O_RDONLY/; # O_RDONLY is used in generate_salt
23
use Fcntl qw/O_RDONLY/; # O_RDONLY is used in generate_salt
24
use List::MoreUtils qw/ any /;
24
use List::MoreUtils qw/ any /;
25
use String::Random qw( random_string );
26
27
use C4::Context;
25
28
26
use base 'Exporter';
29
use base 'Exporter';
27
30
Lines 134-139 sub generate_salt { Link Here
134
    return $string;
137
    return $string;
135
}
138
}
136
139
140
=head2 is_password_valid
141
142
my ( $is_valid, $error ) = is_password_valid( $password );
143
144
return $is_valid == 1 if the password match minPasswordLength and RequireStrongPassword conditions
145
otherwise return $is_valid == 0 and $error will contain the error ('too_short' or 'too_weak')
146
147
=cut
148
149
sub is_password_valid {
150
    my ($password) = @_;
151
    my $minPasswordLength = C4::Context->preference('minPasswordLength');
152
    $minPasswordLength = 3 if not $minPasswordLength or $minPasswordLength < 3;
153
    if ( length($password) < $minPasswordLength ) {
154
        return ( 0, 'too_short' );
155
    }
156
    elsif ( C4::Context->preference('RequireStrongPassword') ) {
157
        return ( 0, 'too_weak' )
158
          if $password !~ m|(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{$minPasswordLength,}|;
159
    }
160
    return ( 0, 'has_whitespaces' ) if $password =~ m[^\s|\s$];
161
    return ( 1, undef );
162
}
163
164
=head2 generate_password
165
166
my password = generate_password();
167
168
Generate a password according to the minPasswordLength and RequireStrongPassword.
169
170
=cut
171
172
sub generate_password {
173
    my $minPasswordLength = C4::Context->preference('minPasswordLength');
174
    $minPasswordLength = 8 if not $minPasswordLength or $minPasswordLength < 8;
175
176
    my ( $password, $is_valid );
177
    do {
178
        $password = random_string('.' x $minPasswordLength );
179
        ( $is_valid, undef ) = is_password_valid( $password );
180
    } while not $is_valid;
181
    return $password;
182
}
183
184
137
=head2 get_script_name
185
=head2 get_script_name
138
186
139
This returns the correct script name, for use in redirecting back to the correct page after showing
187
This returns the correct script name, for use in redirecting back to the correct page after showing
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-password.tt (-3 / +9 lines)
Lines 93-101 Link Here
93
		[% IF ( BADUSERID ) %]
93
		[% IF ( BADUSERID ) %]
94
        <li>You have entered a username that already exists. Please choose another one.</li>
94
        <li>You have entered a username that already exists. Please choose another one.</li>
95
		[% END %]
95
		[% END %]
96
		[% IF ( SHORTPASSWORD ) %]
96
        [% IF ( ERROR_password_too_short ) %]
97
		<li><strong>The password entered is too short</strong>. Password must be at least [% minPasswordLength %] characters.</li>
97
            <li id="ERROR_short_password">Password must be at least [% minPasswordLength %] characters long.</li>
98
		[% END %]
98
        [% END %]
99
        [% IF ( ERROR_password_too_weak ) %]
100
            <li id="ERROR_weak_password">Password must contain at least one digit, one lowercase and one uppercase.</li>
101
        [% END %]
102
        [% IF ( ERROR_password_has_whitespaces ) %]
103
            <li id="ERROR_weak_password">Password must not contain leading or trailing whitespaces.</li>
104
        [% END %]
99
		[% IF ( NOPERMISSION ) %]
105
		[% IF ( NOPERMISSION ) %]
100
		<li>You do not have permission to edit this patron's login information.</li>
106
		<li>You do not have permission to edit this patron's login information.</li>
101
		[% END %]
107
		[% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt (-5 / +14 lines)
Lines 198-206 $(document).ready(function() { Link Here
198
			[% IF ( ERROR_dateexpiry ) %]
198
			[% IF ( ERROR_dateexpiry ) %]
199
				<li id="ERROR_dateexpiry">Date of expiration is invalid.</li>
199
				<li id="ERROR_dateexpiry">Date of expiration is invalid.</li>
200
			[% END %]
200
			[% END %]
201
			[% IF ( ERROR_short_password ) %]
201
            [% IF ( ERROR_password_too_short ) %]
202
				<li id="ERROR_short_password">Password must be at least [% minPasswordLength %] characters long.</li>
202
                <li id="ERROR_short_password">Password must be at least [% minPasswordLength %] characters long.</li>
203
			[% END %]
203
            [% END %]
204
            [% IF ( ERROR_password_too_weak ) %]
205
                <li id="ERROR_weak_password">Password must contain at least one digit, one lowercase and one uppercase.</li>
206
            [% END %]
207
            [% IF ( ERROR_password_has_whitespaces ) %]
208
                <li id="ERROR_weak_password">Password must not contain leading or trailing whitespaces.</li>
209
            [% END %]
204
			[% IF ( ERROR_password_mismatch ) %]
210
			[% IF ( ERROR_password_mismatch ) %]
205
				<li id="ERROR_password_mismatch">Passwords do not match.</li>
211
				<li id="ERROR_password_mismatch">Passwords do not match.</li>
206
			[% END %]
212
			[% END %]
Lines 887-894 $(document).ready(function() { Link Here
887
				[% END %]
893
				[% END %]
888
			[% END %]
894
			[% END %]
889
			[% END %]
895
			[% END %]
890
	  [% IF ( mandatorypassword ) %]<span class="required">Required</span>[% END %][% IF ( ERROR_short_password ) %]<span class="required">Password is too short</span>[% END %]
896
            [% IF ( mandatorypassword ) %]<span class="required">Required</span>[% END %]
891
    <div class="hint">Minimum password length: [% minPasswordLength %]</div>
897
            [% IF ( ERROR_password_too_short ) %]<span class="required">Password is too short</span>[% END %]
898
            [% IF ( ERROR_password_too_weak ) %]<span class="required">Password is too weak</span>[% END %]
899
            [% IF ( ERROR_password_has_whitespaces ) %]<span class="required">Password has leading or trailing whitespaces</span>[% END %]
900
            <div class="hint">Minimum password length: [% minPasswordLength %]</div>
892
		</li>
901
		</li>
893
		<li>
902
		<li>
894
			[% IF ( mandatorypassword ) %]
903
			[% IF ( mandatorypassword ) %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt (-2 / +9 lines)
Lines 65-72 Link Here
65
                                [% IF field == "emailpro" %]<li>Contact information: <a href="#borrower_emailpro">secondary email address</a></li>[% END %]
65
                                [% IF field == "emailpro" %]<li>Contact information: <a href="#borrower_emailpro">secondary email address</a></li>[% END %]
66
                                [% IF field == "B_email" %]<li>Alternate address information: <a href="#borrower_B_email">email address</a></li>[% END %]
66
                                [% IF field == "B_email" %]<li>Alternate address information: <a href="#borrower_B_email">email address</a></li>[% END %]
67
                                [% IF field == "password_match" %]<li>Passwords do not match! <a href="#password">password</a></li>[% END %]
67
                                [% IF field == "password_match" %]<li>Passwords do not match! <a href="#password">password</a></li>[% END %]
68
                                [% IF field == "password_invalid" %]<li>Password does not meet minimum requirements! <a href="#password">password</a></li>[% END %]
68
                                [% IF field == "password_too_short" %]
69
                                [% IF field == "password_spaces" %]<li>Password contains leading and/or trailing spaces! <a href="#password">password</a></li>[% END %]
69
                                    <li>Password must be at least [% minPasswordLength %] characters long.</li>
70
                                [% END %]
71
                                [% IF field == "password_too_weak" %]
72
                                    <li>Password must contain at least one digit, one lowercase and one uppercase.</li>
73
                                [% END %]
74
                                [% IF field == "password_has_whitespaces" %]
75
                                    <li>Password must not contain leading or trailing whitespaces.</li>
76
                                [% END %]
70
                                [% IF field == "duplicate_email" %]
77
                                [% IF field == "duplicate_email" %]
71
                                    <li>This email address already exists in our database.</li>
78
                                    <li>This email address already exists in our database.</li>
72
                                [% END %]
79
                                [% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-passwd.tt (-6 / +10 lines)
Lines 29-46 Link Here
29
                        <div class="alert">
29
                        <div class="alert">
30
                            <h3>There was a problem with your submission</h3>
30
                            <h3>There was a problem with your submission</h3>
31
                            <p>
31
                            <p>
32
                                [% IF ( PassMismatch ) %]
32
                                [% IF ( passwords_mismatch ) %]
33
                                Passwords do not match.  Please re-type your new password.
33
                                Passwords do not match.  Please re-type your new password.
34
                                [% END %]
34
                                [% END %]
35
                                [% IF ( ShortPass ) %]
35
                                [% IF password_too_short %]
36
                                Your new password must be at least [% minPasswordLength%] characters long.
36
                                    Password must be at least [% minPasswordLength %] characters long.
37
                                [% END %]
37
                                [% END %]
38
                                [% IF password_too_weak %]
39
                                    Password must contain at least one digit, one lowercase and one uppercase.
40
                                [% END %]
41
                                [% IF password_has_whitespaces %]
42
                                    Password must not contain leading or trailing whitespaces.
43
                                [% END %]
44
38
                                [% IF ( WrongPass ) %]
45
                                [% IF ( WrongPass ) %]
39
                                Your current password was entered incorrectly.  If this problem persists, please ask a librarian to reset your password for you.
46
                                Your current password was entered incorrectly.  If this problem persists, please ask a librarian to reset your password for you.
40
                                [% END %]
47
                                [% END %]
41
                                [% IF PasswordContainsTrailingSpaces %]
42
                                    Your password contains leading and/or trailing spaces.
43
                                [% END %]
44
                            </p>
48
                            </p>
45
                        </div>
49
                        </div>
46
                    [% END # /IF Error_messages %]
50
                    [% END # /IF Error_messages %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-password-recovery.tt (-4 / +7 lines)
Lines 60-68 Link Here
60
                        <br/>If you did not receive this email, you can request a new one: <a href="/cgi-bin/koha/opac-password-recovery.pl?resendEmail=true&email=[% email %]&username=[% username %]">Get new password recovery link</a>
60
                        <br/>If you did not receive this email, you can request a new one: <a href="/cgi-bin/koha/opac-password-recovery.pl?resendEmail=true&email=[% email %]&username=[% username %]">Get new password recovery link</a>
61
                    [% ELSIF (errPassNotMatch) %]
61
                    [% ELSIF (errPassNotMatch) %]
62
                        The passwords do not match.
62
                        The passwords do not match.
63
                    [% ELSIF (errPassTooShort) %]
63
                    [% ELSIF password_too_short %]
64
                        Your chosen password is too short.
64
                        <li>Password must be at least [% minPasswordLength %] characters long.</li>
65
                        <br/>The password must contain at least [% minPassLength %] characters.
65
                    [% ELSIF password_too_weak %]
66
                        <li>Password must contain at least one digit, one lowercase and one uppercase.</li>
67
                    [% ELSIF password_has_whitespaces %]
68
                        <li>Password must not contain leading or trailing whitespaces.</li>
66
                    [% ELSIF (errLinkNotValid) %]
69
                    [% ELSIF (errLinkNotValid) %]
67
                        The link you clicked is either invalid, or expired.
70
                        The link you clicked is either invalid, or expired.
68
                        <br/>Be sure you used the link from the email, or contact library staff for assistance.
71
                        <br/>Be sure you used the link from the email, or contact library staff for assistance.
Lines 92-98 Link Here
92
                    <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post">
95
                    <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post">
93
                        <input type="hidden" name="koha_login_context" value="opac" />
96
                        <input type="hidden" name="koha_login_context" value="opac" />
94
                        <fieldset>
97
                        <fieldset>
95
                            <div class="alert alert-info">The password must contain at least [% minPassLength %] characters.</div>
98
                            <div class="alert alert-info">The password must contain at least [% minPasswordLength %] characters.</div>
96
                            <label for="password">New password:</label>
99
                            <label for="password">New password:</label>
97
                            <input type="password" id="password" size="40" name="password" />
100
                            <input type="password" id="password" size="40" name="password" />
98
                            <label for="repeatPassword">Confirm new password:</label>
101
                            <label for="repeatPassword">Confirm new password:</label>
(-)a/members/member-password.pl (-4 / +10 lines)
Lines 15-20 use C4::Members; Link Here
15
use C4::Circulation;
15
use C4::Circulation;
16
use CGI qw ( -utf8 );
16
use CGI qw ( -utf8 );
17
use C4::Members::Attributes qw(GetBorrowerAttributes);
17
use C4::Members::Attributes qw(GetBorrowerAttributes);
18
use Koha::AuthUtils;
18
use Koha::Patron::Images;
19
use Koha::Patron::Images;
19
use Koha::Token;
20
use Koha::Token;
20
21
Lines 59-69 if ( ( $member ne $loggedinuser ) && ( $bor->{'category_type'} eq 'S' ) ) { Link Here
59
60
60
push( @errors, 'NOMATCH' ) if ( ( $newpassword && $newpassword2 ) && ( $newpassword ne $newpassword2 ) );
61
push( @errors, 'NOMATCH' ) if ( ( $newpassword && $newpassword2 ) && ( $newpassword ne $newpassword2 ) );
61
62
62
my $minpw = C4::Context->preference('minPasswordLength');
63
if ( $newpassword and not @errors ) {
63
$minpw = 3 if not $minpw or $minpw < 3;
64
    my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $newpassword );
64
push( @errors, 'SHORTPASSWORD' ) if ( $newpassword && $minpw && ( length($newpassword) < $minpw ) );
65
    unless ( $is_valid ) {
66
        push @errors, 'ERROR_password_too_short' if $error eq 'too_short';
67
        push @errors, 'ERROR_password_too_weak' if $error eq 'too_weak';
68
        push @errors, 'ERROR_password_has_whitespaces' if $error eq 'has_whitespaces';
69
    }
70
}
65
71
66
if ( $newpassword && !scalar(@errors) ) {
72
if ( $newpassword and not @errors) {
67
73
68
    die "Wrong CSRF token"
74
    die "Wrong CSRF token"
69
        unless Koha::Token->new->check_csrf({
75
        unless Koha::Token->new->check_csrf({
(-)a/members/memberentry.pl (-4 / +11 lines)
Lines 37-42 use C4::Koha; Link Here
37
use C4::Log;
37
use C4::Log;
38
use C4::Letters;
38
use C4::Letters;
39
use C4::Form::MessagingPreferences;
39
use C4::Form::MessagingPreferences;
40
use Koha::AuthUtils;
40
use Koha::AuthorisedValues;
41
use Koha::AuthorisedValues;
41
use Koha::Patron::Debarments;
42
use Koha::Patron::Debarments;
42
use Koha::Cities;
43
use Koha::Cities;
Lines 340-352 if ($op eq 'save' || $op eq 'insert'){ Link Here
340
  unless (Check_Userid($userid,$borrowernumber)) {
341
  unless (Check_Userid($userid,$borrowernumber)) {
341
    push @errors, "ERROR_login_exist";
342
    push @errors, "ERROR_login_exist";
342
  }
343
  }
343
  
344
344
  my $password = $input->param('password');
345
  my $password = $input->param('password');
345
  my $password2 = $input->param('password2');
346
  my $password2 = $input->param('password2');
346
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
347
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
347
  my $minpw = C4::Context->preference('minPasswordLength');
348
348
  $minpw = 3 if not $minpw or $minpw < 3;
349
  if ( $password and $password ne '****' ) {
349
  push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) );
350
      my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $password );
351
      unless ( $is_valid ) {
352
          push @errors, 'ERROR_password_too_short' if $error eq 'too_short';
353
          push @errors, 'ERROR_password_too_weak' if $error eq 'too_weak';
354
          push @errors, 'ERROR_password_has_whitespaces' if $error eq 'has_whitespaces';
355
      }
356
  }
350
357
351
  # Validate emails
358
  # Validate emails
352
  my $emailprimary = $input->param('email');
359
  my $emailprimary = $input->param('email');
(-)a/opac/opac-memberentry.pl (-7 / +11 lines)
Lines 28-33 use C4::Output; Link Here
28
use C4::Members;
28
use C4::Members;
29
use C4::Members::Attributes qw( GetBorrowerAttributes );
29
use C4::Members::Attributes qw( GetBorrowerAttributes );
30
use C4::Form::MessagingPreferences;
30
use C4::Form::MessagingPreferences;
31
use Koha::AuthUtils;
32
use Koha::Patrons;
33
use Koha::Patron::Modification;
34
use Koha::Patron::Modifications;
31
use C4::Scrubber;
35
use C4::Scrubber;
32
use Email::Valid;
36
use Email::Valid;
33
use Koha::DateUtils;
37
use Koha::DateUtils;
Lines 165-171 if ( $action eq 'create' ) { Link Here
165
                $verification_token = md5_hex( time().{}.rand().{}.$$ );
169
                $verification_token = md5_hex( time().{}.rand().{}.$$ );
166
            }
170
            }
167
171
168
            $borrower{password}           = random_string("..........");
172
            $borrower{password}           = Koha::AuthUtils::generate_password;
169
            $borrower{verification_token} = $verification_token;
173
            $borrower{verification_token} = $verification_token;
170
174
171
            Koha::Patron::Modification->new( \%borrower )->store();
175
            Koha::Patron::Modification->new( \%borrower )->store();
Lines 384-391 sub CheckMandatoryFields { Link Here
384
}
388
}
385
389
386
sub CheckForInvalidFields {
390
sub CheckForInvalidFields {
387
    my $minpw = C4::Context->preference('minPasswordLength');
388
    $minpw = 3 if not $minpw or $minpw < 3;
389
    my $borrower = shift;
391
    my $borrower = shift;
390
    my @invalidFields;
392
    my @invalidFields;
391
    if ($borrower->{'email'}) {
393
    if ($borrower->{'email'}) {
Lines 409-419 sub CheckForInvalidFields { Link Here
409
    {
411
    {
410
        push( @invalidFields, "password_match" );
412
        push( @invalidFields, "password_match" );
411
    }
413
    }
412
    if ( $borrower->{'password'}  && $minpw && (length($borrower->{'password'}) < $minpw) ) {
413
       push(@invalidFields, "password_invalid");
414
    }
415
    if ( $borrower->{'password'} ) {
414
    if ( $borrower->{'password'} ) {
416
       push(@invalidFields, "password_spaces") if ($borrower->{'password'} =~ /^\s/ or $borrower->{'password'} =~ /\s$/);
415
        my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $borrower->{password} );
416
          unless ( $is_valid ) {
417
              push @invalidFields, 'password_too_short' if $error eq 'too_short';
418
              push @invalidFields, 'password_too_weak' if $error eq 'too_weak';
419
              push @invalidFields, 'password_has_whitespaces' if $error eq 'has_whitespaces';
420
          }
417
    }
421
    }
418
422
419
    return \@invalidFields;
423
    return \@invalidFields;
(-)a/opac/opac-passwd.pl (-29 / +28 lines)
Lines 45-91 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
45
);
45
);
46
46
47
my $borr = C4::Members::GetMember( borrowernumber => $borrowernumber );
47
my $borr = C4::Members::GetMember( borrowernumber => $borrowernumber );
48
my $minpasslen = C4::Context->preference("minPasswordLength");
49
$minpasslen = 3 if not $minpasslen or $minpasslen < 3;
50
if ( C4::Context->preference("OpacPasswordChange") ) {
48
if ( C4::Context->preference("OpacPasswordChange") ) {
51
    my $sth =  $dbh->prepare("UPDATE borrowers SET password = ? WHERE borrowernumber=?");
49
    my $sth =  $dbh->prepare("UPDATE borrowers SET password = ? WHERE borrowernumber=?");
52
    if (   $query->param('Oldkey')
50
    if (   $query->param('Oldkey')
53
        && $query->param('Newkey')
51
        && $query->param('Newkey')
54
        && $query->param('Confirm') )
52
        && $query->param('Confirm') )
55
    {
53
    {
54
        my $error;
55
        my $new_password = $query->param('Newkey');
56
        my $confirm_password = $query->param('Confirm');
56
        if ( goodkey( $dbh, $borrowernumber, $query->param('Oldkey') ) ) {
57
        if ( goodkey( $dbh, $borrowernumber, $query->param('Oldkey') ) ) {
57
            if ( $query->param('Newkey') =~ m|^\s+| or $query->param('Newkey') =~ m|\s+$| ) {
58
58
                $template->param(
59
            if ( $new_password ne $confirm_password ) {
59
                    Error_messages => 1,
60
                    PasswordContainsTrailingSpaces => 1,
61
                );
62
            }
63
            elsif ( $query->param('Newkey') eq $query->param('Confirm')
64
                && length( $query->param('Confirm') ) >= $minpasslen )
65
            {    # Record password
66
                my $clave = hash_password( $query->param('Newkey') );
67
                $sth->execute( $clave, $borrowernumber );
68
                $template->param( 'password_updated' => '1' );
69
                $template->param( 'borrowernumber'   => $borrowernumber );
70
            }
71
            elsif ( $query->param('Newkey') ne $query->param('Confirm') ) {
72
                $template->param( 'Ask_data'       => '1' );
73
                $template->param( 'Error_messages' => '1' );
74
                $template->param( 'PassMismatch'   => '1' );
75
            }
76
            elsif ( length( $query->param('Confirm') ) < $minpasslen ) {
77
                $template->param( 'Ask_data'       => '1' );
60
                $template->param( 'Ask_data'       => '1' );
78
                $template->param( 'Error_messages' => '1' );
61
                $template->param( 'Error_messages' => '1' );
79
                $template->param( 'ShortPass'      => '1' );
62
                $template->param( 'passwords_mismatch'   => '1' );
80
            }
63
            } else {
81
            else {
64
                my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $new_password );
82
                $template->param( 'Error_messages' => '1' );
65
                unless ( $is_valid ) {
66
                    $error = 'password_too_short' if $error eq 'too_short';
67
                    $error = 'password_too_weak' if $error eq 'too_weak';
68
                    $error = 'password_has_whitespaces' if $error eq 'has_whitespaces';
69
                } else {
70
                    # Password is valid and match
71
                    my $clave = hash_password( $new_password );
72
                    $sth->execute( $clave, $borrowernumber );
73
                    $template->param( 'password_updated' => '1' );
74
                    $template->param( 'borrowernumber'   => $borrowernumber );
75
                }
83
            }
76
            }
84
        }
77
        }
85
        else {
78
        else {
86
            $template->param( 'Ask_data'       => '1' );
79
            $error = 'WrongPass';
87
            $template->param( 'Error_messages' => '1' );
80
        }
88
            $template->param( 'WrongPass'      => '1' );
81
        if ($error) {
82
            $template->param(
83
                Ask_data       => 1,
84
                Error_messages => 1,
85
                $error         => 1,
86
            );
87
89
        }
88
        }
90
    }
89
    }
91
    else {
90
    else {
(-)a/opac/opac-password-recovery.pl (-32 / +25 lines)
Lines 45-52 my $errBadEmail; Link Here
45
45
46
#new password form error
46
#new password form error
47
my $errLinkNotValid;
47
my $errLinkNotValid;
48
my $errPassNotMatch;
49
my $errPassTooShort;
50
48
51
if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
49
if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
52
50
Lines 132-169 if ( $query->param('sendEmail') || $query->param('resendEmail') ) { Link Here
132
elsif ( $query->param('passwordReset') ) {
130
elsif ( $query->param('passwordReset') ) {
133
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
131
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
134
132
135
    my $minPassLength = C4::Context->preference('minPasswordLength');
133
    my $error;
136
    $minPassLength = 3 if not $minPassLength or $minPassLength < 3;
134
    if ( not $borrower_number ) {
137
    #validate password length & match
135
        $error = 'errLinkNotValid';
138
    if (   ($borrower_number)
136
    } elsif ( $password ne $repeatPassword ) {
139
        && ( $password eq $repeatPassword )
137
        $error = 'errPassNotMatch';
140
        && ( length($password) >= $minPassLength ) )
138
    } else {
141
    {    #apply changes
139
        my ( $is_valid, $err) = Koha::AuthUtils::is_password_valid( $password );
142
        Koha::Patrons->find($borrower_number)->update_password( $username, hash_password($password) );
140
        unless ( $is_valid ) {
143
        CompletePasswordRecovery($uniqueKey);
141
            $error = 'password_too_short' if $err eq 'too_short';
144
        $template->param(
142
            $error = 'password_too_weak' if $err eq 'too_weak';
145
            password_reset_done => 1,
143
            $error = 'password_has_whitespaces' if $err eq 'has_whitespaces';
146
            username            => $username
144
        } else {
147
        );
145
            Koha::Patrons->find($borrower_number)->update_password( $username, hash_password($password) );
148
    }
146
            CompletePasswordRecovery($uniqueKey);
149
    else {    #errors
147
            $template->param(
150
        if ( !$borrower_number ) {    #parameters not valid
148
                password_reset_done => 1,
151
            $errLinkNotValid = 1;
149
                username            => $username
152
        }
150
            );
153
        elsif ( $password ne $repeatPassword ) {    #passwords does not match
154
            $errPassNotMatch = 1;
155
        }
156
        elsif ( length($password) < $minPassLength ) {    #password too short
157
            $errPassTooShort = 1;
158
        }
151
        }
152
    }
153
    if ( $error ) {
159
        $template->param(
154
        $template->param(
160
            new_password    => 1,
155
            new_password => 1,
161
            email           => $email,
156
            email        => $email,
162
            uniqueKey       => $uniqueKey,
157
            uniqueKey    => $uniqueKey,
163
            errLinkNotValid => $errLinkNotValid,
158
            hasError     => 1,
164
            errPassNotMatch => $errPassNotMatch,
159
            $error       => 1,
165
            errPassTooShort => $errPassTooShort,
166
            hasError        => 1
167
        );
160
        );
168
    }
161
    }
169
}
162
}
(-)a/t/AuthUtils.t (-2 / +48 lines)
Lines 1-6 Link Here
1
# This file is part of Koha.
1
# This file is part of Koha.
2
#
2
#
3
# Copyright (C) 2013 Equinox Software, Inc.
3
# Copyright (C) 2013 Equinox Software, Inc.
4
# Copyright 2017 Koha Development Team
4
#
5
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# under the terms of the GNU General Public License as published by
Lines 16-26 Link Here
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
18
use Modern::Perl;
19
use Modern::Perl;
19
use Test::More tests => 1;
20
use Test::More tests => 3;
20
21
22
use t::lib::Mocks;
21
use Koha::AuthUtils qw/hash_password/;
23
use Koha::AuthUtils qw/hash_password/;
22
24
23
my $hash1 = hash_password('password');
25
my $hash1 = hash_password('password');
24
my $hash2 = hash_password('password');
26
my $hash2 = hash_password('password');
25
27
26
ok($hash1 ne $hash2, 'random salts used when generating password hash');
28
ok($hash1 ne $hash2, 'random salts used when generating password hash');
27
- 
29
30
subtest 'is_password_valid' => sub {
31
    plan tests => 12;
32
33
    my ( $is_valid, $error );
34
35
    t::lib::Mocks::mock_preference('RequireStrongPassword', 0);
36
    t::lib::Mocks::mock_preference('minPasswordLength', 0);
37
    ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( '12' );
38
    is( $is_valid, 0, 'min password size should be 3' );
39
    is( $error, 'too_short', 'min password size should be 3' );
40
    ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( ' 123' );
41
    is( $is_valid, 0, 'password should not contain leading spaces' );
42
    is( $error, 'has_whitespaces', 'password should not contain leading spaces' );
43
    ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( '123 ' );
44
    is( $is_valid, 0, 'password should not contain trailing spaces' );
45
    is( $error, 'has_whitespaces', 'password should not contain trailing spaces' );
46
    ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( '123' );
47
    is( $is_valid, 1, 'min password size should be 3' );
48
49
    t::lib::Mocks::mock_preference('RequireStrongPassword', 1);
50
    t::lib::Mocks::mock_preference('minPasswordLength', 8);
51
    ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( '12345678' );
52
    is( $is_valid, 0, 'password should be strong' );
53
    is( $error, 'too_weak', 'password should be strong' );
54
    ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( 'abcd1234' );
55
    is( $is_valid, 0, 'strong password should contain uppercase' );
56
    is( $error, 'too_weak', 'strong password should contain uppercase' );
57
58
    ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( 'abcD1234' );
59
    is( $is_valid, 1, 'strong password should contain uppercase' );
60
};
61
62
subtest 'generate_password' => sub {
63
    plan tests => 1;
64
    t::lib::Mocks::mock_preference('RequireStrongPassword', 1);
65
    t::lib::Mocks::mock_preference('minPasswordLength', 8);
66
    my $all_valid = 1;
67
    for ( 1 .. 10 ) {
68
        my $password = Koha::AuthUtils::generate_password;
69
        my ( $is_valid, undef ) = Koha::AuthUtils::is_password_valid( $password );
70
        $all_valid = 0 unless $is_valid;
71
    }
72
    is ( $all_valid, 1, 'generate_password should generate valid passwords' );
73
};

Return to bug 18298