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 196-204 $(document).ready(function() { Link Here
196
			[% IF ( ERROR_dateexpiry ) %]
196
			[% IF ( ERROR_dateexpiry ) %]
197
				<li id="ERROR_dateexpiry">Date of expiration is invalid.</li>
197
				<li id="ERROR_dateexpiry">Date of expiration is invalid.</li>
198
			[% END %]
198
			[% END %]
199
			[% IF ( ERROR_short_password ) %]
199
            [% IF ( ERROR_password_too_short ) %]
200
				<li id="ERROR_short_password">Password must be at least [% minPasswordLength %] characters long.</li>
200
                <li id="ERROR_short_password">Password must be at least [% minPasswordLength %] characters long.</li>
201
			[% END %]
201
            [% END %]
202
            [% IF ( ERROR_password_too_weak ) %]
203
                <li id="ERROR_weak_password">Password must contain at least one digit, one lowercase and one uppercase.</li>
204
            [% END %]
205
            [% IF ( ERROR_password_has_whitespaces ) %]
206
                <li id="ERROR_weak_password">Password must not contain leading or trailing whitespaces.</li>
207
            [% END %]
202
			[% IF ( ERROR_password_mismatch ) %]
208
			[% IF ( ERROR_password_mismatch ) %]
203
				<li id="ERROR_password_mismatch">Passwords do not match.</li>
209
				<li id="ERROR_password_mismatch">Passwords do not match.</li>
204
			[% END %]
210
			[% END %]
Lines 910-917 $(document).ready(function() { Link Here
910
				[% END %]
916
				[% END %]
911
			[% END %]
917
			[% END %]
912
			[% END %]
918
			[% END %]
913
	  [% IF ( mandatorypassword ) %]<span class="required">Required</span>[% END %][% IF ( ERROR_short_password ) %]<span class="required">Password is too short</span>[% END %]
919
            [% IF ( mandatorypassword ) %]<span class="required">Required</span>[% END %]
914
    <div class="hint">Minimum password length: [% minPasswordLength %]</div>
920
            [% IF ( ERROR_password_too_short ) %]<span class="required">Password is too short</span>[% END %]
921
            [% IF ( ERROR_password_too_weak ) %]<span class="required">Password is too weak</span>[% END %]
922
            [% IF ( ERROR_password_has_whitespaces ) %]<span class="required">Password has leading or trailing whitespaces</span>[% END %]
923
            <div class="hint">Minimum password length: [% minPasswordLength %]</div>
915
		</li>
924
		</li>
916
		<li>
925
		<li>
917
			[% IF ( mandatorypassword ) %]
926
			[% 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 63-71 Link Here
63
                        <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>
63
                        <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>
64
                    [% ELSIF (errPassNotMatch) %]
64
                    [% ELSIF (errPassNotMatch) %]
65
                        The passwords do not match.
65
                        The passwords do not match.
66
                    [% ELSIF (errPassTooShort) %]
66
                    [% ELSIF password_too_short %]
67
                        Your chosen password is too short.
67
                        <li>Password must be at least [% minPasswordLength %] characters long.</li>
68
                        <br/>The password must contain at least [% minPassLength %] characters.
68
                    [% ELSIF password_too_weak %]
69
                        <li>Password must contain at least one digit, one lowercase and one uppercase.</li>
70
                    [% ELSIF password_has_whitespaces %]
71
                        <li>Password must not contain leading or trailing whitespaces.</li>
69
                    [% ELSIF (errLinkNotValid) %]
72
                    [% ELSIF (errLinkNotValid) %]
70
                        The link you clicked is either invalid, or expired.
73
                        The link you clicked is either invalid, or expired.
71
                        <br/>Be sure you used the link from the email, or contact library staff for assistance.
74
                        <br/>Be sure you used the link from the email, or contact library staff for assistance.
Lines 95-101 Link Here
95
                    <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post" autocomplete="off">
98
                    <form action="/cgi-bin/koha/opac-password-recovery.pl" method="post" autocomplete="off">
96
                        <input type="hidden" name="koha_login_context" value="opac" />
99
                        <input type="hidden" name="koha_login_context" value="opac" />
97
                        <fieldset>
100
                        <fieldset>
98
                            <div class="alert alert-info">The password must contain at least [% minPassLength %] characters.</div>
101
                            <div class="alert alert-info">The password must contain at least [% minPasswordLength %] characters.</div>
99
                            <label for="password">New password:</label>
102
                            <label for="password">New password:</label>
100
                            <input type="password" id="password" size="40" name="password" />
103
                            <input type="password" id="password" size="40" name="password" />
101
                            <label for="repeatPassword">Confirm new password:</label>
104
                            <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::Token;
19
use Koha::Token;
19
20
20
use Koha::Patrons;
21
use Koha::Patrons;
Lines 66-76 if ( ( $member ne $loggedinuser ) && ( $category_type eq 'S' ) ) { Link Here
66
67
67
push( @errors, 'NOMATCH' ) if ( ( $newpassword && $newpassword2 ) && ( $newpassword ne $newpassword2 ) );
68
push( @errors, 'NOMATCH' ) if ( ( $newpassword && $newpassword2 ) && ( $newpassword ne $newpassword2 ) );
68
69
69
my $minpw = C4::Context->preference('minPasswordLength');
70
if ( $newpassword and not @errors ) {
70
$minpw = 3 if not $minpw or $minpw < 3;
71
    my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $newpassword );
71
push( @errors, 'SHORTPASSWORD' ) if ( $newpassword && $minpw && ( length($newpassword) < $minpw ) );
72
    unless ( $is_valid ) {
73
        push @errors, 'ERROR_password_too_short' if $error eq 'too_short';
74
        push @errors, 'ERROR_password_too_weak' if $error eq 'too_weak';
75
        push @errors, 'ERROR_password_has_whitespaces' if $error eq 'has_whitespaces';
76
    }
77
}
72
78
73
if ( $newpassword && !scalar(@errors) ) {
79
if ( $newpassword and not @errors) {
74
80
75
    die "Wrong CSRF token"
81
    die "Wrong CSRF token"
76
        unless Koha::Token->new->check_csrf({
82
        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 353-365 if ($op eq 'save' || $op eq 'insert'){ Link Here
353
  unless (Check_Userid($userid,$borrowernumber)) {
354
  unless (Check_Userid($userid,$borrowernumber)) {
354
    push @errors, "ERROR_login_exist";
355
    push @errors, "ERROR_login_exist";
355
  }
356
  }
356
  
357
357
  my $password = $input->param('password');
358
  my $password = $input->param('password');
358
  my $password2 = $input->param('password2');
359
  my $password2 = $input->param('password2');
359
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
360
  push @errors, "ERROR_password_mismatch" if ( $password ne $password2 );
360
  my $minpw = C4::Context->preference('minPasswordLength');
361
361
  $minpw = 3 if not $minpw or $minpw < 3;
362
  if ( $password and $password ne '****' ) {
362
  push @errors, "ERROR_short_password" if( $password && $minpw && $password ne '****' && (length($password) < $minpw) );
363
      my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $password );
364
      unless ( $is_valid ) {
365
          push @errors, 'ERROR_password_too_short' if $error eq 'too_short';
366
          push @errors, 'ERROR_password_too_weak' if $error eq 'too_weak';
367
          push @errors, 'ERROR_password_has_whitespaces' if $error eq 'has_whitespaces';
368
      }
369
  }
363
370
364
  # Validate emails
371
  # Validate emails
365
  my $emailprimary = $input->param('email');
372
  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 386-393 sub CheckMandatoryFields { Link Here
386
}
390
}
387
391
388
sub CheckForInvalidFields {
392
sub CheckForInvalidFields {
389
    my $minpw = C4::Context->preference('minPasswordLength');
390
    $minpw = 3 if not $minpw or $minpw < 3;
391
    my $borrower = shift;
393
    my $borrower = shift;
392
    my @invalidFields;
394
    my @invalidFields;
393
    if ($borrower->{'email'}) {
395
    if ($borrower->{'email'}) {
Lines 421-431 sub CheckForInvalidFields { Link Here
421
    {
423
    {
422
        push( @invalidFields, "password_match" );
424
        push( @invalidFields, "password_match" );
423
    }
425
    }
424
    if ( $borrower->{'password'}  && $minpw && (length($borrower->{'password'}) < $minpw) ) {
425
       push(@invalidFields, "password_invalid");
426
    }
427
    if ( $borrower->{'password'} ) {
426
    if ( $borrower->{'password'} ) {
428
       push(@invalidFields, "password_spaces") if ($borrower->{'password'} =~ /^\s/ or $borrower->{'password'} =~ /\s$/);
427
        my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $borrower->{password} );
428
          unless ( $is_valid ) {
429
              push @invalidFields, 'password_too_short' if $error eq 'too_short';
430
              push @invalidFields, 'password_too_weak' if $error eq 'too_weak';
431
              push @invalidFields, 'password_has_whitespaces' if $error eq 'has_whitespaces';
432
          }
429
    }
433
    }
430
434
431
    return \@invalidFields;
435
    return \@invalidFields;
(-)a/opac/opac-passwd.pl (-29 / +28 lines)
Lines 46-92 my ( $template, $borrowernumber, $cookie ) = get_template_and_user( Link Here
46
);
46
);
47
47
48
my $patron = Koha::Patrons->find( $borrowernumber );
48
my $patron = Koha::Patrons->find( $borrowernumber );
49
my $minpasslen = C4::Context->preference("minPasswordLength");
50
$minpasslen = 3 if not $minpasslen or $minpasslen < 3;
51
if ( C4::Context->preference("OpacPasswordChange") ) {
49
if ( C4::Context->preference("OpacPasswordChange") ) {
52
    my $sth =  $dbh->prepare("UPDATE borrowers SET password = ? WHERE borrowernumber=?");
50
    my $sth =  $dbh->prepare("UPDATE borrowers SET password = ? WHERE borrowernumber=?");
53
    if (   $query->param('Oldkey')
51
    if (   $query->param('Oldkey')
54
        && $query->param('Newkey')
52
        && $query->param('Newkey')
55
        && $query->param('Confirm') )
53
        && $query->param('Confirm') )
56
    {
54
    {
55
        my $error;
56
        my $new_password = $query->param('Newkey');
57
        my $confirm_password = $query->param('Confirm');
57
        if ( goodkey( $dbh, $borrowernumber, $query->param('Oldkey') ) ) {
58
        if ( goodkey( $dbh, $borrowernumber, $query->param('Oldkey') ) ) {
58
            if ( $query->param('Newkey') =~ m|^\s+| or $query->param('Newkey') =~ m|\s+$| ) {
59
59
                $template->param(
60
            if ( $new_password ne $confirm_password ) {
60
                    Error_messages => 1,
61
                    PasswordContainsTrailingSpaces => 1,
62
                );
63
            }
64
            elsif ( $query->param('Newkey') eq $query->param('Confirm')
65
                && length( $query->param('Confirm') ) >= $minpasslen )
66
            {    # Record password
67
                my $clave = hash_password( $query->param('Newkey') );
68
                $sth->execute( $clave, $borrowernumber );
69
                $template->param( 'password_updated' => '1' );
70
                $template->param( 'borrowernumber'   => $borrowernumber );
71
            }
72
            elsif ( $query->param('Newkey') ne $query->param('Confirm') ) {
73
                $template->param( 'Ask_data'       => '1' );
74
                $template->param( 'Error_messages' => '1' );
75
                $template->param( 'PassMismatch'   => '1' );
76
            }
77
            elsif ( length( $query->param('Confirm') ) < $minpasslen ) {
78
                $template->param( 'Ask_data'       => '1' );
61
                $template->param( 'Ask_data'       => '1' );
79
                $template->param( 'Error_messages' => '1' );
62
                $template->param( 'Error_messages' => '1' );
80
                $template->param( 'ShortPass'      => '1' );
63
                $template->param( 'passwords_mismatch'   => '1' );
81
            }
64
            } else {
82
            else {
65
                my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $new_password );
83
                $template->param( 'Error_messages' => '1' );
66
                unless ( $is_valid ) {
67
                    $error = 'password_too_short' if $error eq 'too_short';
68
                    $error = 'password_too_weak' if $error eq 'too_weak';
69
                    $error = 'password_has_whitespaces' if $error eq 'has_whitespaces';
70
                } else {
71
                    # Password is valid and match
72
                    my $clave = hash_password( $new_password );
73
                    $sth->execute( $clave, $borrowernumber );
74
                    $template->param( 'password_updated' => '1' );
75
                    $template->param( 'borrowernumber'   => $borrowernumber );
76
                }
84
            }
77
            }
85
        }
78
        }
86
        else {
79
        else {
87
            $template->param( 'Ask_data'       => '1' );
80
            $error = 'WrongPass';
88
            $template->param( 'Error_messages' => '1' );
81
        }
89
            $template->param( 'WrongPass'      => '1' );
82
        if ($error) {
83
            $template->param(
84
                Ask_data       => 1,
85
                Error_messages => 1,
86
                $error         => 1,
87
            );
88
90
        }
89
        }
91
    }
90
    }
92
    else {
91
    else {
(-)a/opac/opac-password-recovery.pl (-32 / +25 lines)
Lines 46-53 my $errBadEmail; Link Here
46
46
47
#new password form error
47
#new password form error
48
my $errLinkNotValid;
48
my $errLinkNotValid;
49
my $errPassNotMatch;
50
my $errPassTooShort;
51
49
52
if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
50
if ( $query->param('sendEmail') || $query->param('resendEmail') ) {
53
51
Lines 144-181 if ( $query->param('sendEmail') || $query->param('resendEmail') ) { Link Here
144
elsif ( $query->param('passwordReset') ) {
142
elsif ( $query->param('passwordReset') ) {
145
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
143
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
146
144
147
    my $minPassLength = C4::Context->preference('minPasswordLength');
145
    my $error;
148
    $minPassLength = 3 if not $minPassLength or $minPassLength < 3;
146
    if ( not $borrower_number ) {
149
    #validate password length & match
147
        $error = 'errLinkNotValid';
150
    if (   ($borrower_number)
148
    } elsif ( $password ne $repeatPassword ) {
151
        && ( $password eq $repeatPassword )
149
        $error = 'errPassNotMatch';
152
        && ( length($password) >= $minPassLength ) )
150
    } else {
153
    {    #apply changes
151
        my ( $is_valid, $err) = Koha::AuthUtils::is_password_valid( $password );
154
        Koha::Patrons->find($borrower_number)->update_password( $username, hash_password($password) );
152
        unless ( $is_valid ) {
155
        CompletePasswordRecovery($uniqueKey);
153
            $error = 'password_too_short' if $err eq 'too_short';
156
        $template->param(
154
            $error = 'password_too_weak' if $err eq 'too_weak';
157
            password_reset_done => 1,
155
            $error = 'password_has_whitespaces' if $err eq 'has_whitespaces';
158
            username            => $username
156
        } else {
159
        );
157
            Koha::Patrons->find($borrower_number)->update_password( $username, hash_password($password) );
160
    }
158
            CompletePasswordRecovery($uniqueKey);
161
    else {    #errors
159
            $template->param(
162
        if ( !$borrower_number ) {    #parameters not valid
160
                password_reset_done => 1,
163
            $errLinkNotValid = 1;
161
                username            => $username
164
        }
162
            );
165
        elsif ( $password ne $repeatPassword ) {    #passwords does not match
166
            $errPassNotMatch = 1;
167
        }
168
        elsif ( length($password) < $minPassLength ) {    #password too short
169
            $errPassTooShort = 1;
170
        }
163
        }
164
    }
165
    if ( $error ) {
171
        $template->param(
166
        $template->param(
172
            new_password    => 1,
167
            new_password => 1,
173
            email           => $email,
168
            email        => $email,
174
            uniqueKey       => $uniqueKey,
169
            uniqueKey    => $uniqueKey,
175
            errLinkNotValid => $errLinkNotValid,
170
            hasError     => 1,
176
            errPassNotMatch => $errPassNotMatch,
171
            $error       => 1,
177
            errPassTooShort => $errPassTooShort,
178
            hasError        => 1
179
        );
172
        );
180
    }
173
    }
181
}
174
}
(-)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