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 385-392 sub CheckMandatoryFields { Link Here
385
}
389
}
386
390
387
sub CheckForInvalidFields {
391
sub CheckForInvalidFields {
388
    my $minpw = C4::Context->preference('minPasswordLength');
389
    $minpw = 3 if not $minpw or $minpw < 3;
390
    my $borrower = shift;
392
    my $borrower = shift;
391
    my @invalidFields;
393
    my @invalidFields;
392
    if ($borrower->{'email'}) {
394
    if ($borrower->{'email'}) {
Lines 410-420 sub CheckForInvalidFields { Link Here
410
    {
412
    {
411
        push( @invalidFields, "password_match" );
413
        push( @invalidFields, "password_match" );
412
    }
414
    }
413
    if ( $borrower->{'password'}  && $minpw && (length($borrower->{'password'}) < $minpw) ) {
414
       push(@invalidFields, "password_invalid");
415
    }
416
    if ( $borrower->{'password'} ) {
415
    if ( $borrower->{'password'} ) {
417
       push(@invalidFields, "password_spaces") if ($borrower->{'password'} =~ /^\s/ or $borrower->{'password'} =~ /\s$/);
416
        my ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( $borrower->{password} );
417
          unless ( $is_valid ) {
418
              push @invalidFields, 'password_too_short' if $error eq 'too_short';
419
              push @invalidFields, 'password_too_weak' if $error eq 'too_weak';
420
              push @invalidFields, 'password_has_whitespaces' if $error eq 'has_whitespaces';
421
          }
418
    }
422
    }
419
423
420
    return \@invalidFields;
424
    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 143-180 if ( $query->param('sendEmail') || $query->param('resendEmail') ) { Link Here
143
elsif ( $query->param('passwordReset') ) {
141
elsif ( $query->param('passwordReset') ) {
144
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
142
    ( $borrower_number, $username ) = GetValidLinkInfo($uniqueKey);
145
143
146
    my $minPassLength = C4::Context->preference('minPasswordLength');
144
    my $error;
147
    $minPassLength = 3 if not $minPassLength or $minPassLength < 3;
145
    if ( not $borrower_number ) {
148
    #validate password length & match
146
        $error = 'errLinkNotValid';
149
    if (   ($borrower_number)
147
    } elsif ( $password ne $repeatPassword ) {
150
        && ( $password eq $repeatPassword )
148
        $error = 'errPassNotMatch';
151
        && ( length($password) >= $minPassLength ) )
149
    } else {
152
    {    #apply changes
150
        my ( $is_valid, $err) = Koha::AuthUtils::is_password_valid( $password );
153
        Koha::Patrons->find($borrower_number)->update_password( $username, hash_password($password) );
151
        unless ( $is_valid ) {
154
        CompletePasswordRecovery($uniqueKey);
152
            $error = 'password_too_short' if $err eq 'too_short';
155
        $template->param(
153
            $error = 'password_too_weak' if $err eq 'too_weak';
156
            password_reset_done => 1,
154
            $error = 'password_has_whitespaces' if $err eq 'has_whitespaces';
157
            username            => $username
155
        } else {
158
        );
156
            Koha::Patrons->find($borrower_number)->update_password( $username, hash_password($password) );
159
    }
157
            CompletePasswordRecovery($uniqueKey);
160
    else {    #errors
158
            $template->param(
161
        if ( !$borrower_number ) {    #parameters not valid
159
                password_reset_done => 1,
162
            $errLinkNotValid = 1;
160
                username            => $username
163
        }
161
            );
164
        elsif ( $password ne $repeatPassword ) {    #passwords does not match
165
            $errPassNotMatch = 1;
166
        }
167
        elsif ( length($password) < $minPassLength ) {    #password too short
168
            $errPassTooShort = 1;
169
        }
162
        }
163
    }
164
    if ( $error ) {
170
        $template->param(
165
        $template->param(
171
            new_password    => 1,
166
            new_password => 1,
172
            email           => $email,
167
            email        => $email,
173
            uniqueKey       => $uniqueKey,
168
            uniqueKey    => $uniqueKey,
174
            errLinkNotValid => $errLinkNotValid,
169
            hasError     => 1,
175
            errPassNotMatch => $errPassNotMatch,
170
            $error       => 1,
176
            errPassTooShort => $errPassTooShort,
177
            hasError        => 1
178
        );
171
        );
179
    }
172
    }
180
}
173
}
(-)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