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

(-)a/C4/Auth.pm (-181 / +91 lines)
Lines 868-976 sub checkauth { Link Here
868
    elsif ( $emailaddress) {
868
    elsif ( $emailaddress) {
869
        # the Google OpenID Connect passes an email address
869
        # the Google OpenID Connect passes an email address
870
    }
870
    }
871
    elsif ( $sessionID = $query->cookie("CGISESSID") )
871
    elsif ( $sessionID = $query->cookie("CGISESSID") ) {    # assignment, not comparison
872
    {    # assignment, not comparison
872
        my ( $return, $more_info );
873
        $session = get_session($sessionID);
873
        ( $return, $session, $more_info ) = check_cookie_auth( $sessionID, $flags,
874
        C4::Context->_new_userenv($sessionID);
874
            { remote_addr => $ENV{REMOTE_ADDR} }
875
        my ( $ip, $lasttime, $sessiontype );
875
        );
876
        my $s_userid = '';
877
        if ($session) {
878
            $s_userid = $session->param('id') // '';
879
            C4::Context->set_userenv(
880
                $session->param('number'),       $s_userid,
881
                $session->param('cardnumber'),   $session->param('firstname'),
882
                $session->param('surname'),      $session->param('branch'),
883
                $session->param('branchname'),   $session->param('flags'),
884
                $session->param('emailaddress'), $session->param('shibboleth'),
885
                $session->param('desk_id'),      $session->param('desk_name'),
886
                $session->param('register_id'),  $session->param('register_name')
887
            );
888
            Koha::Logger->get->debug(sprintf "AUTH_SESSION: (%s)\t%s %s - %s", map { $session->param($_) || q{} } qw(cardnumber firstname surname branch));
889
            $ip          = $session->param('ip');
890
            $lasttime    = $session->param('lasttime');
891
            $userid      = $s_userid;
892
            $sessiontype = $session->param('sessiontype') || '';
893
        }
894
        if ( ( $query->param('koha_login_context') && ( $q_userid ne $s_userid ) )
895
            || ( $cas && $query->param('ticket') && !C4::Context->userenv->{'id'} )
896
            || ( $shib && $shib_login && !$logout && !C4::Context->userenv->{'id'} )
897
        ) {
898
899
            #if a user enters an id ne to the id in the current session, we need to log them in...
900
            #first we need to clear the anonymous session...
901
            $anon_search_history = $session->param('search_history');
902
            $session->delete();
903
            $session->flush;
904
            C4::Context->_unset_userenv($sessionID);
905
            $sessionID = undef;
906
            $userid    = undef;
907
        }
908
        elsif ($logout) {
909
876
910
            # voluntary logout the user
877
        if ( $return eq 'ok' ) {
911
            # check wether the user was using their shibboleth session or a local one
878
            Koha::Logger->get->debug(sprintf "AUTH_SESSION: (%s)\t%s %s - %s", map { $session->param($_) || q{} } qw(cardnumber firstname surname branch));
912
            my $shibSuccess = C4::Context->userenv->{'shibboleth'};
913
            $session->delete();
914
            $session->flush;
915
            C4::Context->_unset_userenv($sessionID);
916
879
917
            $sessionID = undef;
880
            my $s_userid = $session->param('id');
918
            $userid    = undef;
881
            $userid      = $s_userid;
919
882
920
            if ($cas and $caslogout) {
883
            if ( ( $query->param('koha_login_context') && ( $q_userid ne $s_userid ) )
921
                logout_cas($query, $type);
884
                || ( $cas && $query->param('ticket') && !C4::Context->userenv->{'id'} )
922
            }
885
                || ( $shib && $shib_login && !$logout && !C4::Context->userenv->{'id'} )
886
            ) {
923
887
924
            # If we are in a shibboleth session (shibboleth is enabled, a shibboleth match attribute is set and matches koha matchpoint)
888
                #if a user enters an id ne to the id in the current session, we need to log them in...
925
            if ( $shib and $shib_login and $shibSuccess) {
889
                #first we need to clear the anonymous session...
926
                logout_shib($query);
890
                $anon_search_history = $session->param('search_history');
891
                $session->delete();
892
                $session->flush;
893
                C4::Context->_unset_userenv($sessionID);
927
            }
894
            }
928
        }
895
            elsif ($logout) {
929
        elsif ( !$lasttime || ( $lasttime < time() - $timeout ) ) {
930
896
931
            # timed logout
897
                # voluntary logout the user
932
            $info{'timed_out'} = 1;
898
                # check wether the user was using their shibboleth session or a local one
933
            if ($session) {
899
                my $shibSuccess = C4::Context->userenv->{'shibboleth'};
934
                $session->delete();
900
                $session->delete();
935
                $session->flush;
901
                $session->flush;
936
            }
902
                C4::Context->_unset_userenv($sessionID);
937
            C4::Context->_unset_userenv($sessionID);
938
903
939
            $userid    = undef;
904
                if ($cas and $caslogout) {
940
            $sessionID = undef;
905
                    logout_cas($query, $type);
941
        }
906
                }
942
        elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $ENV{'REMOTE_ADDR'} ) {
943
907
944
            # Different ip than originally logged in from
908
                # If we are in a shibboleth session (shibboleth is enabled, a shibboleth match attribute is set and matches koha matchpoint)
945
            $info{'oldip'}        = $ip;
909
                if ( $shib and $shib_login and $shibSuccess) {
946
            $info{'newip'}        = $ENV{'REMOTE_ADDR'};
910
                    logout_shib($query);
947
            $info{'different_ip'} = 1;
911
                }
948
            $session->delete();
912
            } else {
949
            $session->flush;
950
            C4::Context->_unset_userenv($sessionID);
951
913
952
            $sessionID = undef;
914
                $cookie = $query->cookie(
953
            $userid    = undef;
915
                    -name     => 'CGISESSID',
954
        }
916
                    -value    => $session->id,
955
        else {
917
                    -HttpOnly => 1,
956
            $cookie = $query->cookie(
918
                    -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
957
                -name     => 'CGISESSID',
919
                );
958
                -value    => $session->id,
920
959
                -HttpOnly => 1,
921
                my $sessiontype = $session->param('sessiontype') || '';
960
                -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
922
                unless ( $sessiontype && $sessiontype eq 'anon' ) {    #if this is an anonymous session, we want to update the session, but not behave as if they are logged in...
961
            );
923
                    $flags = haspermission( $userid, $flagsrequired );
962
            $session->param( 'lasttime', time() );
924
                    if ($flags) {
963
            unless ( $sessiontype && $sessiontype eq 'anon' ) {    #if this is an anonymous session, we want to update the session, but not behave as if they are logged in...
925
                        $loggedin = 1;
964
                $flags = haspermission( $userid, $flagsrequired );
926
                    } else {
965
                if ($flags) {
927
                        $info{'nopermission'} = 1;
966
                    $loggedin = 1;
928
                    }
967
                } else {
968
                    $info{'nopermission'} = 1;
969
                }
929
                }
970
            }
930
            }
931
        } elsif ( !$logout ) {
932
            if ( $return eq 'expired' ) {
933
                $info{timed_out} = 1;
934
            } elsif ( $return eq 'restricted' ) {
935
                $info{oldip}        = $more_info->{old_ip};
936
                $info{newip}        = $more_info->{new_ip};
937
                $info{different_ip} = 1;
938
            }
971
        }
939
        }
972
    }
940
    }
973
    unless ( $userid || $sessionID ) {
941
942
    unless ( $loggedin ) {
943
        $sessionID = undef;
944
        $userid    = undef;
945
    }
946
947
    unless ( $userid ) {
974
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
948
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
975
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
949
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
976
950
Lines 985-991 sub checkauth { Link Here
985
        C4::Context->_new_userenv($sessionID);
959
        C4::Context->_new_userenv($sessionID);
986
        $cookie = $query->cookie(
960
        $cookie = $query->cookie(
987
            -name     => 'CGISESSID',
961
            -name     => 'CGISESSID',
988
            -value    => $session->id,
962
            -value    => $sessionID,
989
            -HttpOnly => 1,
963
            -HttpOnly => 1,
990
            -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
964
            -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
991
        );
965
        );
Lines 1317-1324 sub checkauth { Link Here
1317
        script_name                           => get_script_name(),
1291
        script_name                           => get_script_name(),
1318
        casAuthentication                     => C4::Context->preference("casAuthentication"),
1292
        casAuthentication                     => C4::Context->preference("casAuthentication"),
1319
        shibbolethAuthentication              => $shib,
1293
        shibbolethAuthentication              => $shib,
1320
        SessionRestrictionByIP                => C4::Context->preference("SessionRestrictionByIP"),
1321
        suggestion                            => C4::Context->preference("suggestion"),
1294
        suggestion                            => C4::Context->preference("suggestion"),
1295
        SessionRestrictionByIP                => C4::Context->preference("SessionRestrictionByIP"),
1322
        virtualshelves                        => C4::Context->preference("virtualshelves"),
1296
        virtualshelves                        => C4::Context->preference("virtualshelves"),
1323
        LibraryName                           => "" . C4::Context->preference("LibraryName"),
1297
        LibraryName                           => "" . C4::Context->preference("LibraryName"),
1324
        LibraryNameTitle                      => "" . $LibraryNameTitle,
1298
        LibraryNameTitle                      => "" . $LibraryNameTitle,
Lines 1460-1465 Possible return values in C<$status> are: Link Here
1460
1434
1461
=item "expired -- session cookie has expired; API user should resubmit userid and password
1435
=item "expired -- session cookie has expired; API user should resubmit userid and password
1462
1436
1437
=item "restricted" -- The IP has changed (if SessionRestrictionByIP)
1438
1463
=back
1439
=back
1464
1440
1465
=cut
1441
=cut
Lines 1486-1565 sub check_api_auth { Link Here
1486
        return ( "maintenance", undef, undef );
1462
        return ( "maintenance", undef, undef );
1487
    }
1463
    }
1488
1464
1489
    # FIXME -- most of what follows is a copy-and-paste
1465
    my ( $sessionID, $session );
1490
    # of code from checkauth.  There is an obvious need
1491
    # for refactoring to separate the various parts of
1492
    # the authentication code, but as of 2007-11-19 this
1493
    # is deferred so as to not introduce bugs into the
1494
    # regular authentication code for Koha 3.0.
1495
1496
    # see if we have a valid session cookie already
1497
    # however, if a userid parameter is present (i.e., from
1498
    # a form submission, assume that any current cookie
1499
    # is to be ignored
1500
    my $sessionID = undef;
1501
    unless ( $query->param('userid') ) {
1466
    unless ( $query->param('userid') ) {
1502
        $sessionID = $query->cookie("CGISESSID");
1467
        $sessionID = $query->cookie("CGISESSID");
1503
    }
1468
    }
1504
    if ( $sessionID && not( $cas && $query->param('PT') ) ) {
1469
    if ( $sessionID && not( $cas && $query->param('PT') ) ) {
1505
        my $session = get_session($sessionID);
1506
        C4::Context->_new_userenv($sessionID);
1507
        if ($session) {
1508
            C4::Context->interface($session->param('interface'));
1509
            C4::Context->set_userenv(
1510
                $session->param('number'),       $session->param('id'),
1511
                $session->param('cardnumber'),   $session->param('firstname'),
1512
                $session->param('surname'),      $session->param('branch'),
1513
                $session->param('branchname'),   $session->param('flags'),
1514
                $session->param('emailaddress'), $session->param('shibboleth'),
1515
                $session->param('desk_id'),      $session->param('desk_name'),
1516
                $session->param('register_id'),  $session->param('register_name')
1517
            );
1518
1470
1519
            my $ip       = $session->param('ip');
1471
        my $return;
1520
            my $lasttime = $session->param('lasttime');
1472
        ( $return, $session, undef ) = check_cookie_auth(
1521
            my $userid   = $session->param('id');
1473
            $sessionID, $flagsrequired, { remote_addr => $ENV{REMOTE_ADDR} } );
1522
            if ( $lasttime < time() - $timeout ) {
1523
1474
1524
                # time out
1475
        return ( $return, undef, undef ) # Cookie auth failed
1525
                $session->delete();
1476
            if $return ne "ok";
1526
                $session->flush;
1477
1527
                C4::Context->_unset_userenv($sessionID);
1478
        my $cookie = $query->cookie(
1528
                $userid    = undef;
1479
            -name     => 'CGISESSID',
1529
                $sessionID = undef;
1480
            -value    => $session->id,
1530
                return ( "expired", undef, undef );
1481
            -HttpOnly => 1,
1531
            } elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $ENV{'REMOTE_ADDR'} ) {
1482
            -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
1483
        );
1484
        return ( $return, undef, $session );
1532
1485
1533
                # IP address changed
1534
                $session->delete();
1535
                $session->flush;
1536
                C4::Context->_unset_userenv($sessionID);
1537
                $userid    = undef;
1538
                $sessionID = undef;
1539
                return ( "expired", undef, undef );
1540
            } else {
1541
                my $cookie = $query->cookie(
1542
                    -name     => 'CGISESSID',
1543
                    -value    => $session->id,
1544
                    -HttpOnly => 1,
1545
                    -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
1546
                );
1547
                $session->param( 'lasttime', time() );
1548
                my $flags = haspermission( $userid, $flagsrequired );
1549
                if ($flags) {
1550
                    return ( "ok", $cookie, $sessionID );
1551
                } else {
1552
                    $session->delete();
1553
                    $session->flush;
1554
                    C4::Context->_unset_userenv($sessionID);
1555
                    $userid    = undef;
1556
                    $sessionID = undef;
1557
                    return ( "failed", undef, undef );
1558
                }
1559
            }
1560
        } else {
1561
            return ( "expired", undef, undef );
1562
        }
1563
    } else {
1486
    } else {
1564
1487
1565
        # new login
1488
        # new login
Lines 1712-1729 Possible return values in C<$status> are: Link Here
1712
1635
1713
=item "expired -- session cookie has expired; API user should resubmit userid and password
1636
=item "expired -- session cookie has expired; API user should resubmit userid and password
1714
1637
1638
=item "restricted" -- The IP has changed (if SessionRestrictionByIP)
1639
1715
=back
1640
=back
1716
1641
1717
=cut
1642
=cut
1718
1643
1719
sub check_cookie_auth {
1644
sub check_cookie_auth {
1720
    my $cookie        = shift;
1645
    my $sessionID     = shift;
1721
    my $flagsrequired = shift;
1646
    my $flagsrequired = shift;
1722
    my $params        = shift;
1647
    my $params        = shift;
1723
1648
1724
    my $remote_addr = $params->{remote_addr} || $ENV{REMOTE_ADDR};
1649
    my $remote_addr = $params->{remote_addr} || $ENV{REMOTE_ADDR};
1725
    my $dbh     = C4::Context->dbh;
1726
    my $timeout = _timeout_syspref();
1727
1650
1728
    unless ( C4::Context->preference('Version') ) {
1651
    unless ( C4::Context->preference('Version') ) {
1729
1652
Lines 1740-1766 sub check_cookie_auth { Link Here
1740
        return ( "maintenance", undef );
1663
        return ( "maintenance", undef );
1741
    }
1664
    }
1742
1665
1743
    # FIXME -- most of what follows is a copy-and-paste
1744
    # of code from checkauth.  There is an obvious need
1745
    # for refactoring to separate the various parts of
1746
    # the authentication code, but as of 2007-11-23 this
1747
    # is deferred so as to not introduce bugs into the
1748
    # regular authentication code for Koha 3.0.
1749
1750
    # see if we have a valid session cookie already
1666
    # see if we have a valid session cookie already
1751
    # however, if a userid parameter is present (i.e., from
1667
    # however, if a userid parameter is present (i.e., from
1752
    # a form submission, assume that any current cookie
1668
    # a form submission, assume that any current cookie
1753
    # is to be ignored
1669
    # is to be ignored
1754
    unless ( defined $cookie and $cookie ) {
1670
    unless ( defined $sessionID and $sessionID ) {
1755
        return ( "failed", undef );
1671
        return ( "failed", undef );
1756
    }
1672
    }
1757
    my $sessionID = $cookie;
1758
    my $session   = get_session($sessionID);
1673
    my $session   = get_session($sessionID);
1759
    C4::Context->_new_userenv($sessionID);
1674
    C4::Context->_new_userenv($sessionID);
1760
    if ($session) {
1675
    if ($session) {
1761
        C4::Context->interface($session->param('interface'));
1676
        C4::Context->interface($session->param('interface'));
1762
        C4::Context->set_userenv(
1677
        C4::Context->set_userenv(
1763
            $session->param('number'),       $session->param('id'),
1678
            $session->param('number'),       $session->param('id') // '',
1764
            $session->param('cardnumber'),   $session->param('firstname'),
1679
            $session->param('cardnumber'),   $session->param('firstname'),
1765
            $session->param('surname'),      $session->param('branch'),
1680
            $session->param('surname'),      $session->param('branch'),
1766
            $session->param('branchname'),   $session->param('flags'),
1681
            $session->param('branchname'),   $session->param('flags'),
Lines 1769-1785 sub check_cookie_auth { Link Here
1769
            $session->param('register_id'),  $session->param('register_name')
1684
            $session->param('register_id'),  $session->param('register_name')
1770
        );
1685
        );
1771
1686
1687
        my $userid   = $session->param('id');
1772
        my $ip       = $session->param('ip');
1688
        my $ip       = $session->param('ip');
1773
        my $lasttime = $session->param('lasttime');
1689
        my $lasttime = $session->param('lasttime');
1774
        my $userid   = $session->param('id');
1690
        my $timeout = _timeout_syspref();
1775
        if ( $lasttime < time() - $timeout ) {
1691
1692
        if ( !$lasttime || ( $lasttime < time() - $timeout ) ) {
1776
1693
1777
            # time out
1694
            # time out
1778
            $session->delete();
1695
            $session->delete();
1779
            $session->flush;
1696
            $session->flush;
1780
            C4::Context->_unset_userenv($sessionID);
1697
            C4::Context->_unset_userenv($sessionID);
1781
            $userid    = undef;
1782
            $sessionID = undef;
1783
            return ("expired", undef);
1698
            return ("expired", undef);
1784
        } elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $remote_addr ) {
1699
        } elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $remote_addr ) {
1785
1700
Lines 1787-1806 sub check_cookie_auth { Link Here
1787
            $session->delete();
1702
            $session->delete();
1788
            $session->flush;
1703
            $session->flush;
1789
            C4::Context->_unset_userenv($sessionID);
1704
            C4::Context->_unset_userenv($sessionID);
1790
            $userid    = undef;
1705
            return ( "restricted", undef, { old_ip => $ip, new_ip => $remote_addr});
1791
            $sessionID = undef;
1792
            return ( "expired", undef );
1793
        } else {
1706
        } else {
1794
            $session->param( 'lasttime', time() );
1707
            $session->param( 'lasttime', time() );
1795
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1708
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1796
            if ($flags) {
1709
            if ($flags) {
1797
                return ( "ok", $sessionID );
1710
                return ( "ok", $session );
1798
            } else {
1711
            } else {
1799
                $session->delete();
1712
                $session->delete();
1800
                $session->flush;
1713
                $session->flush;
1801
                C4::Context->_unset_userenv($sessionID);
1714
                C4::Context->_unset_userenv($sessionID);
1802
                $userid    = undef;
1803
                $sessionID = undef;
1804
                return ( "failed", undef );
1715
                return ( "failed", undef );
1805
            }
1716
            }
1806
        }
1717
        }
1807
- 

Return to bug 28785