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

(-)a/C4/Auth.pm (-13 / +12 lines)
Lines 380-386 sub get_template_and_user { Link Here
380
                # we add them to the logged-in search history
380
                # we add them to the logged-in search history
381
                my @recentSearches = C4::Search::History::get_from_session( { cgi => $in->{'query'} } );
381
                my @recentSearches = C4::Search::History::get_from_session( { cgi => $in->{'query'} } );
382
                if (@recentSearches) {
382
                if (@recentSearches) {
383
                    my $dbh   = C4::Context->dbh;
384
                    my $query = q{
383
                    my $query = q{
385
                        INSERT INTO search_history(userid, sessionid, query_desc, query_cgi, type,  total, time )
384
                        INSERT INTO search_history(userid, sessionid, query_desc, query_cgi, type,  total, time )
386
                        VALUES (?, ?, ?, ?, ?, ?, ?)
385
                        VALUES (?, ?, ?, ?, ?, ?, ?)
Lines 810-816 sub checkauth { Link Here
810
          @allowed_scripts_for_private_opac;
809
          @allowed_scripts_for_private_opac;
811
    }
810
    }
812
811
813
    my $dbh     = C4::Context->dbh;
814
    my $timeout = _timeout_syspref();
812
    my $timeout = _timeout_syspref();
815
813
816
    _version_check( $type, $query );
814
    _version_check( $type, $query );
Lines 1002-1008 sub checkauth { Link Here
1002
                my $retuserid;
1000
                my $retuserid;
1003
1001
1004
                # Do not pass password here, else shib will not be checked in checkpw.
1002
                # Do not pass password here, else shib will not be checked in checkpw.
1005
                ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $q_userid, undef, $query );
1003
                ( $return, $cardnumber, $retuserid ) = checkpw( $q_userid, undef, $query );
1006
                $userid      = $retuserid;
1004
                $userid      = $retuserid;
1007
                $shibSuccess = $return;
1005
                $shibSuccess = $return;
1008
                $info{'invalidShibLogin'} = 1 unless ($return);
1006
                $info{'invalidShibLogin'} = 1 unless ($return);
Lines 1013-1019 sub checkauth { Link Here
1013
                if ( $cas && $query->param('ticket') ) {
1011
                if ( $cas && $query->param('ticket') ) {
1014
                    my $retuserid;
1012
                    my $retuserid;
1015
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
1013
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
1016
                      checkpw( $dbh, $userid, $password, $query, $type );
1014
                      checkpw( $userid, $password, $query, $type );
1017
                    $userid = $retuserid;
1015
                    $userid = $retuserid;
1018
                    $info{'invalidCasLogin'} = 1 unless ($return);
1016
                    $info{'invalidCasLogin'} = 1 unless ($return);
1019
                }
1017
                }
Lines 1073-1079 sub checkauth { Link Here
1073
                else {
1071
                else {
1074
                    my $retuserid;
1072
                    my $retuserid;
1075
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
1073
                    ( $return, $cardnumber, $retuserid, $cas_ticket ) =
1076
                      checkpw( $dbh, $q_userid, $password, $query, $type );
1074
                      checkpw( $q_userid, $password, $query, $type );
1077
                    $userid = $retuserid if ($retuserid);
1075
                    $userid = $retuserid if ($retuserid);
1078
                    $info{'invalid_username_or_password'} = 1 unless ($return);
1076
                    $info{'invalid_username_or_password'} = 1 unless ($return);
1079
                }
1077
                }
Lines 1101-1106 sub checkauth { Link Here
1101
                    FROM borrowers
1099
                    FROM borrowers
1102
                    LEFT JOIN branches on borrowers.branchcode=branches.branchcode
1100
                    LEFT JOIN branches on borrowers.branchcode=branches.branchcode
1103
                    ";
1101
                    ";
1102
                    my $dbh = C4::Context->dbh;
1104
                    my $sth = $dbh->prepare("$select where userid=?");
1103
                    my $sth = $dbh->prepare("$select where userid=?");
1105
                    $sth->execute($userid);
1104
                    $sth->execute($userid);
1106
                    unless ( $sth->rows ) {
1105
                    unless ( $sth->rows ) {
Lines 1442-1448 sub check_api_auth { Link Here
1442
1441
1443
    my $query         = shift;
1442
    my $query         = shift;
1444
    my $flagsrequired = shift;
1443
    my $flagsrequired = shift;
1445
    my $dbh     = C4::Context->dbh;
1446
    my $timeout = _timeout_syspref();
1444
    my $timeout = _timeout_syspref();
1447
1445
1448
    unless ( C4::Context->preference('Version') ) {
1446
    unless ( C4::Context->preference('Version') ) {
Lines 1548-1554 sub check_api_auth { Link Here
1548
1546
1549
            # In case of a CAS authentication, we use the ticket instead of the password
1547
            # In case of a CAS authentication, we use the ticket instead of the password
1550
            my $PT = $query->param('PT');
1548
            my $PT = $query->param('PT');
1551
            ( $return, $cardnumber, $userid, $cas_ticket ) = check_api_auth_cas( $dbh, $PT, $query );    # EXTERNAL AUTH
1549
            ( $return, $cardnumber, $userid, $cas_ticket ) = check_api_auth_cas( $PT, $query );    # EXTERNAL AUTH
1552
        } else {
1550
        } else {
1553
1551
1554
            # User / password auth
1552
            # User / password auth
Lines 1558-1564 sub check_api_auth { Link Here
1558
                return ( "failed", undef, undef );
1556
                return ( "failed", undef, undef );
1559
            }
1557
            }
1560
            my $newuserid;
1558
            my $newuserid;
1561
            ( $return, $cardnumber, $newuserid, $cas_ticket ) = checkpw( $dbh, $userid, $password, $query );
1559
            ( $return, $cardnumber, $newuserid, $cas_ticket ) = checkpw( $userid, $password, $query );
1562
        }
1560
        }
1563
1561
1564
        if ( $return and haspermission( $userid, $flagsrequired ) ) {
1562
        if ( $return and haspermission( $userid, $flagsrequired ) ) {
Lines 1579-1584 sub check_api_auth { Link Here
1579
                    $userflags,      $branchcode, $branchname,
1577
                    $userflags,      $branchcode, $branchname,
1580
                    $emailaddress
1578
                    $emailaddress
1581
                );
1579
                );
1580
                my $dbh = C4::Context->dbh;
1582
                my $sth =
1581
                my $sth =
1583
                  $dbh->prepare(
1582
                  $dbh->prepare(
1584
"select borrowernumber, firstname, surname, flags, borrowers.branchcode, branches.branchname as branchname, email from borrowers left join branches on borrowers.branchcode=branches.branchcode where userid=?"
1583
"select borrowernumber, firstname, surname, flags, borrowers.branchcode, branches.branchname as branchname, email from borrowers left join branches on borrowers.branchcode=branches.branchcode where userid=?"
Lines 1697-1703 sub check_cookie_auth { Link Here
1697
    my $params        = shift;
1696
    my $params        = shift;
1698
1697
1699
    my $remote_addr = $params->{remote_addr} || $ENV{REMOTE_ADDR};
1698
    my $remote_addr = $params->{remote_addr} || $ENV{REMOTE_ADDR};
1700
    my $dbh     = C4::Context->dbh;
1701
    my $timeout = _timeout_syspref();
1699
    my $timeout = _timeout_syspref();
1702
1700
1703
    unless ( C4::Context->preference('Version') ) {
1701
    unless ( C4::Context->preference('Version') ) {
Lines 1833-1839 sub get_session { Link Here
1833
# Currently it's only passed from C4::SIP::ILS::Patron::check_password, but
1831
# Currently it's only passed from C4::SIP::ILS::Patron::check_password, but
1834
# not having a userenv defined could cause a crash.
1832
# not having a userenv defined could cause a crash.
1835
sub checkpw {
1833
sub checkpw {
1836
    my ( $dbh, $userid, $password, $query, $type, $no_set_userenv ) = @_;
1834
    my ( $userid, $password, $query, $type, $no_set_userenv ) = @_;
1837
    $type = 'opac' unless $type;
1835
    $type = 'opac' unless $type;
1838
1836
1839
    # Get shibboleth login attribute
1837
    # Get shibboleth login attribute
Lines 1870-1876 sub checkpw { Link Here
1870
        # In case of a CAS authentication, we use the ticket instead of the password
1868
        # In case of a CAS authentication, we use the ticket instead of the password
1871
        my $ticket = $query->param('ticket');
1869
        my $ticket = $query->param('ticket');
1872
        $query->delete('ticket');                                   # remove ticket to come back to original URL
1870
        $query->delete('ticket');                                   # remove ticket to come back to original URL
1873
        my ( $retval, $retcard, $retuserid, $cas_ticket ) = checkpw_cas( $dbh, $ticket, $query, $type );    # EXTERNAL AUTH
1871
        my ( $retval, $retcard, $retuserid, $cas_ticket ) = checkpw_cas( $ticket, $query, $type );    # EXTERNAL AUTH
1874
        if ( $retval ) {
1872
        if ( $retval ) {
1875
            @return = ( $retval, $retcard, $retuserid, $cas_ticket );
1873
            @return = ( $retval, $retcard, $retuserid, $cas_ticket );
1876
        } else {
1874
        } else {
Lines 1904-1910 sub checkpw { Link Here
1904
1902
1905
    # INTERNAL AUTH
1903
    # INTERNAL AUTH
1906
    if ( $check_internal_as_fallback ) {
1904
    if ( $check_internal_as_fallback ) {
1907
        @return = checkpw_internal( $dbh, $userid, $password, $no_set_userenv);
1905
        @return = checkpw_internal( $userid, $password, $no_set_userenv);
1908
        $passwd_ok = 1 if $return[0] > 0; # 1 or 2
1906
        $passwd_ok = 1 if $return[0] > 0; # 1 or 2
1909
    }
1907
    }
1910
1908
Lines 1927-1937 sub checkpw { Link Here
1927
}
1925
}
1928
1926
1929
sub checkpw_internal {
1927
sub checkpw_internal {
1930
    my ( $dbh, $userid, $password, $no_set_userenv ) = @_;
1928
    my ( $userid, $password, $no_set_userenv ) = @_;
1931
1929
1932
    $password = Encode::encode( 'UTF-8', $password )
1930
    $password = Encode::encode( 'UTF-8', $password )
1933
      if Encode::is_utf8($password);
1931
      if Encode::is_utf8($password);
1934
1932
1933
    my $dbh = C4::Context->dbh;
1935
    my $sth =
1934
    my $sth =
1936
      $dbh->prepare(
1935
      $dbh->prepare(
1937
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?"
1936
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?"
(-)a/C4/Auth_with_cas.pm (-2 / +4 lines)
Lines 92-98 sub login_cas_url { Link Here
92
# In our case : is there a ticket, is it valid and does it match one of our users ?
92
# In our case : is there a ticket, is it valid and does it match one of our users ?
93
sub checkpw_cas {
93
sub checkpw_cas {
94
    $debug and warn "checkpw_cas";
94
    $debug and warn "checkpw_cas";
95
    my ($dbh, $ticket, $query, $type) = @_;
95
    my ($ticket, $query, $type) = @_;
96
    my $retnumber;
96
    my $retnumber;
97
    my ( $cas, $uri ) = _get_cas_and_service($query, undef, $type);
97
    my ( $cas, $uri ) = _get_cas_and_service($query, undef, $type);
98
98
Lines 112-117 sub checkpw_cas { Link Here
112
            # we should store the CAS ticekt too, we need this for single logout https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-Specification.html#233-single-logout
112
            # we should store the CAS ticekt too, we need this for single logout https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-Specification.html#233-single-logout
113
113
114
            # Does it match one of our users ?
114
            # Does it match one of our users ?
115
            my $dbh = C4::Context->dbh;
115
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
116
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
116
            $sth->execute($userid);
117
            $sth->execute($userid);
117
            if ( $sth->rows ) {
118
            if ( $sth->rows ) {
Lines 142-148 sub checkpw_cas { Link Here
142
# Proxy CAS auth
143
# Proxy CAS auth
143
sub check_api_auth_cas {
144
sub check_api_auth_cas {
144
    $debug and warn "check_api_auth_cas";
145
    $debug and warn "check_api_auth_cas";
145
    my ($dbh, $PT, $query, $type) = @_;
146
    my ($PT, $query, $type) = @_;
146
    my $retnumber;
147
    my $retnumber;
147
    my ( $cas, $uri ) = _get_cas_and_service($query, undef, $type);
148
    my ( $cas, $uri ) = _get_cas_and_service($query, undef, $type);
148
149
Lines 163-168 sub check_api_auth_cas { Link Here
163
            # we should store the CAS ticket too, we need this for single logout https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-Specification.html#233-single-logout
164
            # we should store the CAS ticket too, we need this for single logout https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-Specification.html#233-single-logout
164
165
165
            # Does it match one of our users ?
166
            # Does it match one of our users ?
167
            my $dbh = C4::Context->dbh;
166
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
168
            my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?");
167
            $sth->execute($userid);
169
            $sth->execute($userid);
168
            if ( $sth->rows ) {
170
            if ( $sth->rows ) {
(-)a/C4/Auth_with_ldap.pm (-2 / +2 lines)
Lines 109-115 sub search_method { Link Here
109
}
109
}
110
110
111
sub checkpw_ldap {
111
sub checkpw_ldap {
112
    my ($dbh, $userid, $password) = @_;
112
    my ($userid, $password) = @_;
113
    my @hosts = split(',', $prefhost);
113
    my @hosts = split(',', $prefhost);
114
    my $db = Net::LDAP->new(\@hosts);
114
    my $db = Net::LDAP->new(\@hosts);
115
    unless ( $db ) {
115
    unless ( $db ) {
Lines 359-365 sub _do_changepassword { Link Here
359
    $debug and print STDERR "changing local password for borrowernumber=$borrowerid to '$digest'\n";
359
    $debug and print STDERR "changing local password for borrowernumber=$borrowerid to '$digest'\n";
360
    Koha::Patrons->find($borrowerid)->set_password({ password => $password, skip_validation => 1 });
360
    Koha::Patrons->find($borrowerid)->set_password({ password => $password, skip_validation => 1 });
361
361
362
    my ($ok, $cardnum) = checkpw_internal(C4::Context->dbh, $userid, $password);
362
    my ($ok, $cardnum) = checkpw_internal($userid, $password);
363
    return $cardnum if $ok;
363
    return $cardnum if $ok;
364
364
365
    warn "Password mismatch after update to borrowernumber=$borrowerid";
365
    warn "Password mismatch after update to borrowernumber=$borrowerid";
(-)a/C4/ILSDI/Services.pm (-1 / +1 lines)
Lines 381-387 sub AuthenticatePatron { Link Here
381
    my ($cgi) = @_;
381
    my ($cgi) = @_;
382
    my $username = $cgi->param('username');
382
    my $username = $cgi->param('username');
383
    my $password = $cgi->param('password');
383
    my $password = $cgi->param('password');
384
    my ($status, $cardnumber, $userid) = C4::Auth::checkpw( C4::Context->dbh, $username, $password );
384
    my ($status, $cardnumber, $userid) = C4::Auth::checkpw( $username, $password );
385
    if ( $status ) {
385
    if ( $status ) {
386
        # Get the borrower
386
        # Get the borrower
387
        my $patron = Koha::Patrons->find( { userid => $userid } );
387
        my $patron = Koha::Patrons->find( { userid => $userid } );
(-)a/C4/SIP/ILS/Patron.pm (-2 / +1 lines)
Lines 260-268 sub check_password { Link Here
260
    # If the record has a NULL password, accept '' as match
260
    # If the record has a NULL password, accept '' as match
261
    return $pwd eq q{} unless $self->{password};
261
    return $pwd eq q{} unless $self->{password};
262
262
263
    my $dbh = C4::Context->dbh;
264
    my $ret = 0;
263
    my $ret = 0;
265
    ($ret) = checkpw( $dbh, $self->{userid}, $pwd, undef, undef, 1 ); # dbh, userid, query, type, no_set_userenv
264
    ($ret) = checkpw( $self->{userid}, $pwd, undef, undef, 1 ); # userid, query, type, no_set_userenv
266
    return $ret;
265
    return $ret;
267
}
266
}
268
267
(-)a/Koha/REST/V1/Auth.pm (-2 / +1 lines)
Lines 481-488 sub _basic_auth { Link Here
481
    my $decoded_credentials = decode_base64( $credentials );
481
    my $decoded_credentials = decode_base64( $credentials );
482
    my ( $user_id, $password ) = split( /:/, $decoded_credentials, 2 );
482
    my ( $user_id, $password ) = split( /:/, $decoded_credentials, 2 );
483
483
484
    my $dbh = C4::Context->dbh;
484
    unless ( checkpw_internal($user_id, $password ) ) {
485
    unless ( checkpw_internal($dbh, $user_id, $password ) ) {
486
        Koha::Exceptions::Authorization::Unauthorized->throw( error => 'Invalid password' );
485
        Koha::Exceptions::Authorization::Unauthorized->throw( error => 'Invalid password' );
487
    }
486
    }
488
487
(-)a/Koha/REST/V1/Patrons/Password.pm (-2 / +1 lines)
Lines 117-124 sub set_public { Link Here
117
    }
117
    }
118
118
119
    return try {
119
    return try {
120
        my $dbh = C4::Context->dbh;
120
        unless ( checkpw_internal($user->userid, $old_password ) ) {
121
        unless ( checkpw_internal($dbh, $user->userid, $old_password ) ) {
122
            return $c->render(
121
            return $c->render(
123
                status  => 400,
122
                status  => 400,
124
                openapi => { error => "Invalid password" }
123
                openapi => { error => "Invalid password" }
(-)a/opac/sco/sco-main.pl (-2 / +1 lines)
Lines 114-122 my $issuenoconfirm = 1; #don't need to confirm on issue. Link Here
114
my $issuer   = Koha::Patrons->find( $issuerid )->unblessed;
114
my $issuer   = Koha::Patrons->find( $issuerid )->unblessed;
115
my $item     = Koha::Items->find({ barcode => $barcode });
115
my $item     = Koha::Items->find({ barcode => $barcode });
116
if (C4::Context->preference('SelfCheckoutByLogin') && !$patronid) {
116
if (C4::Context->preference('SelfCheckoutByLogin') && !$patronid) {
117
    my $dbh = C4::Context->dbh;
118
    my $resval;
117
    my $resval;
119
    ($resval, $patronid) = checkpw($dbh, $patronlogin, $patronpw);
118
    ($resval, $patronid) = checkpw($patronlogin, $patronpw);
120
}
119
}
121
120
122
my ( $borrower, $patron );
121
my ( $borrower, $patron );
(-)a/t/db_dependent/Auth.t (-12 / +11 lines)
Lines 27-33 BEGIN { Link Here
27
27
28
my $schema  = Koha::Database->schema;
28
my $schema  = Koha::Database->schema;
29
my $builder = t::lib::TestBuilder->new;
29
my $builder = t::lib::TestBuilder->new;
30
my $dbh     = C4::Context->dbh;
31
30
32
# FIXME: SessionStorage defaults to mysql, but it seems to break transaction
31
# FIXME: SessionStorage defaults to mysql, but it seems to break transaction
33
# handling
32
# handling
Lines 133-146 subtest 'no_set_userenv parameter tests' => sub { Link Here
133
    t::lib::Mocks::mock_preference( 'RequireStrongPassword', 0 );
132
    t::lib::Mocks::mock_preference( 'RequireStrongPassword', 0 );
134
    $patron->set_password({ password => $password });
133
    $patron->set_password({ password => $password });
135
134
136
    ok( checkpw( $dbh, $patron->userid, $password, undef, undef, 1 ), 'checkpw returns true' );
135
    ok( checkpw( $patron->userid, $password, undef, undef, 1 ), 'checkpw returns true' );
137
    is( C4::Context->userenv, undef, 'Userenv should be undef as required' );
136
    is( C4::Context->userenv, undef, 'Userenv should be undef as required' );
138
    C4::Context->_new_userenv('DUMMY SESSION');
137
    C4::Context->_new_userenv('DUMMY SESSION');
139
    C4::Context->set_userenv(0,0,0,'firstname','surname', $library->branchcode, 'Library 1', 0, '', '');
138
    C4::Context->set_userenv(0,0,0,'firstname','surname', $library->branchcode, 'Library 1', 0, '', '');
140
    is( C4::Context->userenv->{branch}, $library->branchcode, 'Userenv gives correct branch' );
139
    is( C4::Context->userenv->{branch}, $library->branchcode, 'Userenv gives correct branch' );
141
    ok( checkpw( $dbh, $patron->userid, $password, undef, undef, 1 ), 'checkpw returns true' );
140
    ok( checkpw( $patron->userid, $password, undef, undef, 1 ), 'checkpw returns true' );
142
    is( C4::Context->userenv->{branch}, $library->branchcode, 'Userenv branch is preserved if no_set_userenv is true' );
141
    is( C4::Context->userenv->{branch}, $library->branchcode, 'Userenv branch is preserved if no_set_userenv is true' );
143
    ok( checkpw( $dbh, $patron->userid, $password, undef, undef, 0 ), 'checkpw still returns true' );
142
    ok( checkpw( $patron->userid, $password, undef, undef, 0 ), 'checkpw still returns true' );
144
    isnt( C4::Context->userenv->{branch}, $library->branchcode, 'Userenv branch is overwritten if no_set_userenv is false' );
143
    isnt( C4::Context->userenv->{branch}, $library->branchcode, 'Userenv branch is overwritten if no_set_userenv is false' );
145
};
144
};
146
145
Lines 155-169 subtest 'checkpw lockout tests' => sub { Link Here
155
    t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 1 );
154
    t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 1 );
156
    $patron->set_password({ password => $password });
155
    $patron->set_password({ password => $password });
157
156
158
    my ( $checkpw, undef, undef ) = checkpw( $dbh, $patron->cardnumber, $password, undef, undef, 1 );
157
    my ( $checkpw, undef, undef ) = checkpw( $patron->cardnumber, $password, undef, undef, 1 );
159
    ok( $checkpw, 'checkpw returns true with right password when logging in via cardnumber' );
158
    ok( $checkpw, 'checkpw returns true with right password when logging in via cardnumber' );
160
    ( $checkpw, undef, undef ) = checkpw( $dbh, $patron->userid, "wrong_password", undef, undef, 1 );
159
    ( $checkpw, undef, undef ) = checkpw( $patron->userid, "wrong_password", undef, undef, 1 );
161
    is( $checkpw, 0, 'checkpw returns false when given wrong password' );
160
    is( $checkpw, 0, 'checkpw returns false when given wrong password' );
162
    $patron = $patron->get_from_storage;
161
    $patron = $patron->get_from_storage;
163
    is( $patron->account_locked, 1, "Account is locked from failed login");
162
    is( $patron->account_locked, 1, "Account is locked from failed login");
164
    ( $checkpw, undef, undef ) = checkpw( $dbh, $patron->userid, $password, undef, undef, 1 );
163
    ( $checkpw, undef, undef ) = checkpw( $patron->userid, $password, undef, undef, 1 );
165
    is( $checkpw, undef, 'checkpw returns undef with right password when account locked' );
164
    is( $checkpw, undef, 'checkpw returns undef with right password when account locked' );
166
    ( $checkpw, undef, undef ) = checkpw( $dbh, $patron->cardnumber, $password, undef, undef, 1 );
165
    ( $checkpw, undef, undef ) = checkpw( $patron->cardnumber, $password, undef, undef, 1 );
167
    is( $checkpw, undef, 'checkpw returns undefwith right password when logging in via cardnumber if account locked' );
166
    is( $checkpw, undef, 'checkpw returns undefwith right password when logging in via cardnumber if account locked' );
168
167
169
};
168
};
Lines 361-367 subtest 'Check value of login_attempts in checkpw' => sub { Link Here
361
    $patron->password('123')->store; # yes, deliberately not hashed
360
    $patron->password('123')->store; # yes, deliberately not hashed
362
361
363
    is( $patron->account_locked, 0, 'Patron not locked' );
362
    is( $patron->account_locked, 0, 'Patron not locked' );
364
    my @test = checkpw( $dbh, $patron->userid, '123', undef, 'opac', 1 );
363
    my @test = checkpw( $patron->userid, '123', undef, 'opac', 1 );
365
        # Note: 123 will not be hashed to 123 !
364
        # Note: 123 will not be hashed to 123 !
366
    is( $test[0], 0, 'checkpw should have failed' );
365
    is( $test[0], 0, 'checkpw should have failed' );
367
    $patron->discard_changes; # refresh
366
    $patron->discard_changes; # refresh
Lines 369-375 subtest 'Check value of login_attempts in checkpw' => sub { Link Here
369
    is( $patron->account_locked, 1, 'Check locked status' );
368
    is( $patron->account_locked, 1, 'Check locked status' );
370
369
371
    # And another try to go over the limit: different return value!
370
    # And another try to go over the limit: different return value!
372
    @test = checkpw( $dbh, $patron->userid, '123', undef, 'opac', 1 );
371
    @test = checkpw( $patron->userid, '123', undef, 'opac', 1 );
373
    is( @test, 0, 'checkpw failed again and returns nothing now' );
372
    is( @test, 0, 'checkpw failed again and returns nothing now' );
374
    $patron->discard_changes; # refresh
373
    $patron->discard_changes; # refresh
375
    is( $patron->login_attempts, 3, 'Login attempts not increased anymore' );
374
    is( $patron->login_attempts, 3, 'Login attempts not increased anymore' );
Lines 379-389 subtest 'Check value of login_attempts in checkpw' => sub { Link Here
379
    my $auth = Test::MockModule->new( 'C4::Auth' );
378
    my $auth = Test::MockModule->new( 'C4::Auth' );
380
    $auth->mock( 'checkpw_hash', sub { return 1; } ); # not for production :)
379
    $auth->mock( 'checkpw_hash', sub { return 1; } ); # not for production :)
381
    $patron->login_attempts(0)->store;
380
    $patron->login_attempts(0)->store;
382
    @test = checkpw( $dbh, $patron->userid, '123', undef, 'opac', 1 );
381
    @test = checkpw( $patron->userid, '123', undef, 'opac', 1 );
383
    is( $test[0], 1, 'Build confidence in the mock' );
382
    is( $test[0], 1, 'Build confidence in the mock' );
384
    $patron->login_attempts(-1)->store;
383
    $patron->login_attempts(-1)->store;
385
    is( $patron->account_locked, 1, 'Check administrative lockout' );
384
    is( $patron->account_locked, 1, 'Check administrative lockout' );
386
    @test = checkpw( $dbh, $patron->userid, '123', undef, 'opac', 1 );
385
    @test = checkpw( $patron->userid, '123', undef, 'opac', 1 );
387
    is( @test, 0, 'checkpw gave red' );
386
    is( @test, 0, 'checkpw gave red' );
388
    $patron->discard_changes; # refresh
387
    $patron->discard_changes; # refresh
389
    is( $patron->login_attempts, -1, 'Still locked out' );
388
    is( $patron->login_attempts, -1, 'Still locked out' );
(-)a/t/db_dependent/Auth_with_ldap.t (-14 / +11 lines)
Lines 28-35 use C4::Context; Link Here
28
28
29
use Koha::Patrons;
29
use Koha::Patrons;
30
30
31
my $dbh = '';
32
33
# Start transaction
31
# Start transaction
34
my $schema = Koha::Database->new->schema;
32
my $schema = Koha::Database->new->schema;
35
$schema->storage->txn_begin();
33
$schema->storage->txn_begin();
Lines 131-142 subtest 'checkpw_ldap tests' => sub { Link Here
131
129
132
    plan tests => 4;
130
    plan tests => 4;
133
131
134
    my $dbh = C4::Context->dbh;
135
    ## Connection fail tests
132
    ## Connection fail tests
136
    $desired_connection_result = 'error';
133
    $desired_connection_result = 'error';
137
    warning_is {
134
    warning_is {
138
        $ret =
135
        $ret =
139
          C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola', password => 'hey' );
136
          C4::Auth_with_ldap::checkpw_ldap( 'hola', password => 'hey' );
140
    }
137
    }
141
    'LDAP connexion failed',
138
    'LDAP connexion failed',
142
      'checkpw_ldap prints correct warning if LDAP conexion fails';
139
      'checkpw_ldap prints correct warning if LDAP conexion fails';
Lines 158-164 subtest 'checkpw_ldap tests' => sub { Link Here
158
        reload_ldap_module();
155
        reload_ldap_module();
159
156
160
        warning_like {
157
        warning_like {
161
            $ret = C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola',
158
            $ret = C4::Auth_with_ldap::checkpw_ldap( 'hola',
162
                password => 'hey' );
159
                password => 'hey' );
163
        }
160
        }
164
        qr/Anonymous LDAP bind failed: LDAP error #1: error_name/,
161
        qr/Anonymous LDAP bind failed: LDAP error #1: error_name/,
Lines 171-177 subtest 'checkpw_ldap tests' => sub { Link Here
171
        reload_ldap_module();
168
        reload_ldap_module();
172
169
173
        warning_like {
170
        warning_like {
174
            $ret = C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola',
171
            $ret = C4::Auth_with_ldap::checkpw_ldap( 'hola',
175
                password => 'hey' );
172
                password => 'hey' );
176
        }
173
        }
177
        qr/LDAP bind failed as kohauser hola: LDAP error #1: error_name/,
174
        qr/LDAP bind failed as kohauser hola: LDAP error #1: error_name/,
Lines 204-210 subtest 'checkpw_ldap tests' => sub { Link Here
204
            }
201
            }
205
        );
202
        );
206
203
207
        C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola', password => 'hey' );
204
        C4::Auth_with_ldap::checkpw_ldap( 'hola', password => 'hey' );
208
        ok(
205
        ok(
209
            Koha::Patrons->find($borrower->{borrowernumber})->extended_attributes->count,
206
            Koha::Patrons->find($borrower->{borrowernumber})->extended_attributes->count,
210
            'Extended attributes are not deleted'
207
            'Extended attributes are not deleted'
Lines 219-225 subtest 'checkpw_ldap tests' => sub { Link Here
219
        $patron->delete;
216
        $patron->delete;
220
        reload_ldap_module();
217
        reload_ldap_module();
221
        is(
218
        is(
222
            C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola', password => 'hey' ),
219
            C4::Auth_with_ldap::checkpw_ldap( 'hola', password => 'hey' ),
223
            0,
220
            0,
224
            'checkpw_ldap returns 0 if user lookup returns 0'
221
            'checkpw_ldap returns 0 if user lookup returns 0'
225
        );
222
        );
Lines 228-234 subtest 'checkpw_ldap tests' => sub { Link Here
228
        reload_ldap_module();
225
        reload_ldap_module();
229
226
230
        warning_like {
227
        warning_like {
231
            $ret = C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola',
228
            $ret = C4::Auth_with_ldap::checkpw_ldap( 'hola',
232
                password => 'hey' );
229
                password => 'hey' );
233
        }
230
        }
234
        qr/LDAP bind failed as kohauser hola: LDAP error #1: error_name/,
231
        qr/LDAP bind failed as kohauser hola: LDAP error #1: error_name/,
Lines 246-252 subtest 'checkpw_ldap tests' => sub { Link Here
246
        reload_ldap_module();
243
        reload_ldap_module();
247
244
248
        warning_like {
245
        warning_like {
249
            $ret = C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola',
246
            $ret = C4::Auth_with_ldap::checkpw_ldap( 'hola',
250
                password => 'hey' );
247
                password => 'hey' );
251
        }
248
        }
252
        qr/LDAP bind failed as kohauser hola: LDAP error #1: error_name/,
249
        qr/LDAP bind failed as kohauser hola: LDAP error #1: error_name/,
Lines 271-277 subtest 'checkpw_ldap tests' => sub { Link Here
271
        reload_ldap_module();
268
        reload_ldap_module();
272
269
273
        warning_like {
270
        warning_like {
274
            $ret = C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola',
271
            $ret = C4::Auth_with_ldap::checkpw_ldap( 'hola',
275
                password => 'hey' );
272
                password => 'hey' );
276
        }
273
        }
277
qr/LDAP bind failed as ldapuser cn=Manager,dc=metavore,dc=com: LDAP error #1: error_name/,
274
qr/LDAP bind failed as ldapuser cn=Manager,dc=metavore,dc=com: LDAP error #1: error_name/,
Lines 286-292 qr/LDAP bind failed as ldapuser cn=Manager,dc=metavore,dc=com: LDAP error #1: er Link Here
286
        reload_ldap_module();
283
        reload_ldap_module();
287
284
288
        warning_like {
285
        warning_like {
289
            $ret = C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola',
286
            $ret = C4::Auth_with_ldap::checkpw_ldap( 'hola',
290
                password => 'hey' );
287
                password => 'hey' );
291
        }
288
        }
292
qr/LDAP Auth rejected : invalid password for user 'hola'./,
289
qr/LDAP Auth rejected : invalid password for user 'hola'./,
Lines 300-306 qr/LDAP Auth rejected : invalid password for user 'hola'./, Link Here
300
        reload_ldap_module();
297
        reload_ldap_module();
301
298
302
        warning_like {
299
        warning_like {
303
            $ret = C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola',
300
            $ret = C4::Auth_with_ldap::checkpw_ldap( 'hola',
304
                password => 'hey' );
301
                password => 'hey' );
305
        }
302
        }
306
qr/LDAP bind failed as ldapuser cn=Manager,dc=metavore,dc=com: LDAP error #1: error_name/,
303
qr/LDAP bind failed as ldapuser cn=Manager,dc=metavore,dc=com: LDAP error #1: error_name/,
Lines 313-319 qr/LDAP bind failed as ldapuser cn=Manager,dc=metavore,dc=com: LDAP error #1: er Link Here
313
        reload_ldap_module();
310
        reload_ldap_module();
314
311
315
        warning_like {
312
        warning_like {
316
            $ret = C4::Auth_with_ldap::checkpw_ldap( $dbh, 'hola',
313
            $ret = C4::Auth_with_ldap::checkpw_ldap( 'hola',
317
                password => 'hey' );
314
                password => 'hey' );
318
        }
315
        }
319
qr/LDAP Auth rejected : invalid password for user 'hola'./,
316
qr/LDAP Auth rejected : invalid password for user 'hola'./,
(-)a/t/db_dependent/Log.t (-14 / +10 lines)
Lines 30-36 use t::lib::TestBuilder; Link Here
30
# Make sure we can rollback.
30
# Make sure we can rollback.
31
our $schema  = Koha::Database->new->schema;
31
our $schema  = Koha::Database->new->schema;
32
$schema->storage->txn_begin;
32
$schema->storage->txn_begin;
33
our $dbh = C4::Context->dbh;
34
33
35
subtest 'Existing tests' => sub {
34
subtest 'Existing tests' => sub {
36
    plan tests => 3;
35
    plan tests => 3;
Lines 47-63 subtest 'Existing tests' => sub { Link Here
47
    ok($success, "logaction seemed to work");
46
    ok($success, "logaction seemed to work");
48
47
49
    # We want numbers to be the same between runs.
48
    # We want numbers to be the same between runs.
50
    $dbh->do("DELETE FROM action_logs;");
49
    Koha::ActionLogs->search->delete;
51
50
52
    t::lib::Mocks::mock_preference('CronjobLog',0);
51
    t::lib::Mocks::mock_preference('CronjobLog',0);
53
    cronlogaction();
52
    cronlogaction();
54
    my $cronJobCount = $dbh->selectrow_array("SELECT COUNT(*) FROM action_logs WHERE module='CRONJOBS';",{});
53
    is(Koha::ActionLogs->search({ module => 'CRONJOBS' })->count,0,"Cronjob not logged as expected.");
55
    is($cronJobCount,0,"Cronjob not logged as expected.");
56
54
57
    t::lib::Mocks::mock_preference('CronjobLog',1);
55
    t::lib::Mocks::mock_preference('CronjobLog',1);
58
    cronlogaction();
56
    cronlogaction();
59
    $cronJobCount = $dbh->selectrow_array("SELECT COUNT(*) FROM action_logs WHERE module='CRONJOBS';",{});
57
    is(Koha::ActionLogs->search({ module => 'CRONJOBS' })->count,0,"Cronjob logged as expected.");
60
    is($cronJobCount,1,"Cronjob logged as expected.");
61
};
58
};
62
59
63
subtest 'logaction(): interface is correctly logged' => sub {
60
subtest 'logaction(): interface is correctly logged' => sub {
Lines 65-92 subtest 'logaction(): interface is correctly logged' => sub { Link Here
65
    plan tests => 4;
62
    plan tests => 4;
66
63
67
    # No interface passed, using C4::Context->interface
64
    # No interface passed, using C4::Context->interface
68
    $dbh->do("DELETE FROM action_logs;");
65
    Koha::ActionLogs->search->delete;
69
    C4::Context->interface( 'commandline' );
66
    C4::Context->interface( 'commandline' );
70
    logaction( "MEMBERS", "MODIFY", 1, "test operation");
67
    logaction( "MEMBERS", "MODIFY", 1, "test operation");
71
    my $log = Koha::ActionLogs->search->next;
68
    my $log = Koha::ActionLogs->search->next;
72
    is( $log->interface, 'commandline', 'Interface correctly deduced (commandline)');
69
    is( $log->interface, 'commandline', 'Interface correctly deduced (commandline)');
73
70
74
    # No interface passed, using C4::Context->interface
71
    # No interface passed, using C4::Context->interface
75
    $dbh->do("DELETE FROM action_logs;");
72
    Koha::ActionLogs->search->delete;
76
    C4::Context->interface( 'opac' );
73
    C4::Context->interface( 'opac' );
77
    logaction( "MEMBERS", "MODIFY", 1, "test operation");
74
    logaction( "MEMBERS", "MODIFY", 1, "test operation");
78
    $log = Koha::ActionLogs->search->next;
75
    $log = Koha::ActionLogs->search->next;
79
    is( $log->interface, 'opac', 'Interface correctly deduced (opac)');
76
    is( $log->interface, 'opac', 'Interface correctly deduced (opac)');
80
77
81
    # Explicit interfaces
78
    # Explicit interfaces
82
    $dbh->do("DELETE FROM action_logs;");
79
    Koha::ActionLogs->search->delete;
83
    C4::Context->interface( 'intranet' );
80
    C4::Context->interface( 'intranet' );
84
    logaction( "MEMBERS", "MODIFY", 1, 'test info', 'intranet');
81
    logaction( "MEMBERS", "MODIFY", 1, 'test info', 'intranet');
85
    $log = Koha::ActionLogs->search->next;
82
    $log = Koha::ActionLogs->search->next;
86
    is( $log->interface, 'intranet', 'Passed interface is respected (intranet)');
83
    is( $log->interface, 'intranet', 'Passed interface is respected (intranet)');
87
84
88
    # Explicit interfaces
85
    # Explicit interfaces
89
    $dbh->do("DELETE FROM action_logs;");
86
    Koha::ActionLogs->search->delete;
90
    C4::Context->interface( 'sip' );
87
    C4::Context->interface( 'sip' );
91
    logaction( "MEMBERS", "MODIFY", 1, 'test info', 'sip');
88
    logaction( "MEMBERS", "MODIFY", 1, 'test info', 'sip');
92
    $log = Koha::ActionLogs->search->next;
89
    $log = Koha::ActionLogs->search->next;
Lines 114-120 subtest 'GDPR logging' => sub { Link Here
114
    t::lib::Mocks::mock_preference('AuthFailureLog', 1);
111
    t::lib::Mocks::mock_preference('AuthFailureLog', 1);
115
    my $strong_password = 'N0tStr0ngAnyM0reN0w:)';
112
    my $strong_password = 'N0tStr0ngAnyM0reN0w:)';
116
    $patron->set_password({ password => $strong_password });
113
    $patron->set_password({ password => $strong_password });
117
    my @ret = checkpw( $dbh, $patron->userid, 'WrongPassword', undef, undef, 1);
114
    my @ret = checkpw( $patron->userid, 'WrongPassword', undef, undef, 1);
118
    is( $ret[0], 0, 'Authentication failed' );
115
    is( $ret[0], 0, 'Authentication failed' );
119
    # Look for auth failure but NOT on patron id, pass userid in info parameter
116
    # Look for auth failure but NOT on patron id, pass userid in info parameter
120
    $logs = Koha::ActionLogs->search(
117
    $logs = Koha::ActionLogs->search(
Lines 126-132 subtest 'GDPR logging' => sub { Link Here
126
    );
123
    );
127
    is( $logs->count, 1, 'We should find one auth failure with this userid' );
124
    is( $logs->count, 1, 'We should find one auth failure with this userid' );
128
    t::lib::Mocks::mock_preference('AuthFailureLog', 0);
125
    t::lib::Mocks::mock_preference('AuthFailureLog', 0);
129
    @ret = checkpw( $dbh, $patron->userid, 'WrongPassword', undef, undef, 1);
126
    @ret = checkpw( $patron->userid, 'WrongPassword', undef, undef, 1);
130
    $logs = Koha::ActionLogs->search(
127
    $logs = Koha::ActionLogs->search(
131
        {
128
        {
132
            module => 'AUTH',
129
            module => 'AUTH',
Lines 136-142 subtest 'GDPR logging' => sub { Link Here
136
    );
133
    );
137
    is( $logs->count, 1, 'Still only one failure with this userid' );
134
    is( $logs->count, 1, 'Still only one failure with this userid' );
138
    t::lib::Mocks::mock_preference('AuthSuccessLog', 1);
135
    t::lib::Mocks::mock_preference('AuthSuccessLog', 1);
139
    @ret = checkpw( $dbh, $patron->userid, $strong_password, undef, undef, 1);
136
    @ret = checkpw( $patron->userid, $strong_password, undef, undef, 1);
140
    is( $ret[0], 1, 'Authentication succeeded' );
137
    is( $ret[0], 1, 'Authentication succeeded' );
141
    # Now we can look for patron id
138
    # Now we can look for patron id
142
    $logs = Koha::ActionLogs->search(
139
    $logs = Koha::ActionLogs->search(
143
- 

Return to bug 27342