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

(-)a/C4/Auth.pm (-181 / +88 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, $session, $more_info ) = check_cookie_auth( $sessionID, $flags,
873
        $session = get_session($sessionID);
873
            { remote_addr => $ENV{REMOTE_ADDR} }
874
        C4::Context->_new_userenv($sessionID);
874
        );
875
        my ( $ip, $lasttime, $sessiontype );
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
875
910
            # voluntary logout the user
876
        if ( $return eq 'ok' ) {
911
            # check wether the user was using their shibboleth session or a local one
877
            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
878
917
            $sessionID = undef;
879
            my $s_userid = $session->param('id');
918
            $userid    = undef;
880
            $userid      = $s_userid;
919
881
920
            if ($cas and $caslogout) {
882
            if ( ( $query->param('koha_login_context') && ( $q_userid ne $s_userid ) )
921
                logout_cas($query, $type);
883
                || ( $cas && $query->param('ticket') && !C4::Context->userenv->{'id'} )
922
            }
884
                || ( $shib && $shib_login && !$logout && !C4::Context->userenv->{'id'} )
885
            ) {
923
886
924
            # If we are in a shibboleth session (shibboleth is enabled, a shibboleth match attribute is set and matches koha matchpoint)
887
                #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) {
888
                #first we need to clear the anonymous session...
926
                logout_shib($query);
889
                $anon_search_history = $session->param('search_history');
890
                $session->delete();
891
                $session->flush;
892
                C4::Context->_unset_userenv($sessionID);
927
            }
893
            }
928
        }
894
            elsif ($logout) {
929
        elsif ( !$lasttime || ( $lasttime < time() - $timeout ) ) {
930
895
931
            # timed logout
896
                # voluntary logout the user
932
            $info{'timed_out'} = 1;
897
                # check wether the user was using their shibboleth session or a local one
933
            if ($session) {
898
                my $shibSuccess = C4::Context->userenv->{'shibboleth'};
934
                $session->delete();
899
                $session->delete();
935
                $session->flush;
900
                $session->flush;
936
            }
901
                C4::Context->_unset_userenv($sessionID);
937
            C4::Context->_unset_userenv($sessionID);
938
902
939
            $userid    = undef;
903
                if ($cas and $caslogout) {
940
            $sessionID = undef;
904
                    logout_cas($query, $type);
941
        }
905
                }
942
        elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $ENV{'REMOTE_ADDR'} ) {
943
906
944
            # Different ip than originally logged in from
907
                # If we are in a shibboleth session (shibboleth is enabled, a shibboleth match attribute is set and matches koha matchpoint)
945
            $info{'oldip'}        = $ip;
908
                if ( $shib and $shib_login and $shibSuccess) {
946
            $info{'newip'}        = $ENV{'REMOTE_ADDR'};
909
                    logout_shib($query);
947
            $info{'different_ip'} = 1;
910
                }
948
            $session->delete();
911
            } else {
949
            $session->flush;
950
            C4::Context->_unset_userenv($sessionID);
951
912
952
            $sessionID = undef;
913
                $cookie = $query->cookie(
953
            $userid    = undef;
914
                    -name     => 'CGISESSID',
954
        }
915
                    -value    => $session->id,
955
        else {
916
                    -HttpOnly => 1,
956
            $cookie = $query->cookie(
917
                    -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
957
                -name     => 'CGISESSID',
918
                );
958
                -value    => $session->id,
919
959
                -HttpOnly => 1,
920
                my $sessiontype = $session->param('sessiontype') || '';
960
                -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
921
                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
            );
922
                    $flags = haspermission( $userid, $flagsrequired );
962
            $session->param( 'lasttime', time() );
923
                    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...
924
                        $loggedin = 1;
964
                $flags = haspermission( $userid, $flagsrequired );
925
                    } else {
965
                if ($flags) {
926
                        $info{'nopermission'} = 1;
966
                    $loggedin = 1;
927
                    }
967
                } else {
968
                    $info{'nopermission'} = 1;
969
                }
928
                }
970
            }
929
            }
930
        } elsif ( !$logout ) {
931
            if ( $return eq 'expired' ) {
932
                $info{timed_out} = 1;
933
            } elsif ( $return eq 'restricted' ) {
934
                $info{oldip}        = $more_info->{old_ip};
935
                $info{newip}        = $more_info->{new_ip};
936
                $info{different_ip} = 1;
937
            }
971
        }
938
        }
972
    }
939
    }
973
    unless ( $userid || $sessionID ) {
940
941
    unless ( $loggedin ) {
942
        $sessionID = undef;
943
        $userid    = undef;
944
    }
945
946
    unless ( $userid ) {
974
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
947
        #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()";
948
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
976
949
Lines 985-991 sub checkauth { Link Here
985
        C4::Context->_new_userenv($sessionID);
958
        C4::Context->_new_userenv($sessionID);
986
        $cookie = $query->cookie(
959
        $cookie = $query->cookie(
987
            -name     => 'CGISESSID',
960
            -name     => 'CGISESSID',
988
            -value    => $session->id,
961
            -value    => $sessionID,
989
            -HttpOnly => 1,
962
            -HttpOnly => 1,
990
            -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
963
            -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
991
        );
964
        );
Lines 1317-1324 sub checkauth { Link Here
1317
        script_name                           => get_script_name(),
1290
        script_name                           => get_script_name(),
1318
        casAuthentication                     => C4::Context->preference("casAuthentication"),
1291
        casAuthentication                     => C4::Context->preference("casAuthentication"),
1319
        shibbolethAuthentication              => $shib,
1292
        shibbolethAuthentication              => $shib,
1320
        SessionRestrictionByIP                => C4::Context->preference("SessionRestrictionByIP"),
1321
        suggestion                            => C4::Context->preference("suggestion"),
1293
        suggestion                            => C4::Context->preference("suggestion"),
1294
        SessionRestrictionByIP                => C4::Context->preference("SessionRestrictionByIP"),
1322
        virtualshelves                        => C4::Context->preference("virtualshelves"),
1295
        virtualshelves                        => C4::Context->preference("virtualshelves"),
1323
        LibraryName                           => "" . C4::Context->preference("LibraryName"),
1296
        LibraryName                           => "" . C4::Context->preference("LibraryName"),
1324
        LibraryNameTitle                      => "" . $LibraryNameTitle,
1297
        LibraryNameTitle                      => "" . $LibraryNameTitle,
Lines 1486-1565 sub check_api_auth { Link Here
1486
        return ( "maintenance", undef, undef );
1459
        return ( "maintenance", undef, undef );
1487
    }
1460
    }
1488
1461
1489
    # FIXME -- most of what follows is a copy-and-paste
1462
    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') ) {
1463
    unless ( $query->param('userid') ) {
1502
        $sessionID = $query->cookie("CGISESSID");
1464
        $sessionID = $query->cookie("CGISESSID");
1503
    }
1465
    }
1504
    if ( $sessionID && not( $cas && $query->param('PT') ) ) {
1466
    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
1467
1519
            my $ip       = $session->param('ip');
1468
        my $return;
1520
            my $lasttime = $session->param('lasttime');
1469
        ( $return, $session, undef ) = check_cookie_auth(
1521
            my $userid   = $session->param('id');
1470
            $sessionID, $flagsrequired, { remote_addr => $ENV{REMOTE_ADDR} } );
1522
            if ( $lasttime < time() - $timeout ) {
1523
1471
1524
                # time out
1472
        return ( $return, undef, undef ) # Cookie auth failed
1525
                $session->delete();
1473
            if $return ne "ok";
1526
                $session->flush;
1474
1527
                C4::Context->_unset_userenv($sessionID);
1475
        my $cookie = $query->cookie(
1528
                $userid    = undef;
1476
            -name     => 'CGISESSID',
1529
                $sessionID = undef;
1477
            -value    => $session->id,
1530
                return ( "expired", undef, undef );
1478
            -HttpOnly => 1,
1531
            } elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $ENV{'REMOTE_ADDR'} ) {
1479
            -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
1480
        );
1481
        return ( $return, undef, $session );
1532
1482
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 {
1483
    } else {
1564
1484
1565
        # new login
1485
        # new login
Lines 1712-1729 Possible return values in C<$status> are: Link Here
1712
1632
1713
=item "expired -- session cookie has expired; API user should resubmit userid and password
1633
=item "expired -- session cookie has expired; API user should resubmit userid and password
1714
1634
1635
=item "restricted" -- The IP has changed (if SessionRestrictionByIP)
1636
1715
=back
1637
=back
1716
1638
1717
=cut
1639
=cut
1718
1640
1719
sub check_cookie_auth {
1641
sub check_cookie_auth {
1720
    my $cookie        = shift;
1642
    my $sessionID     = shift;
1721
    my $flagsrequired = shift;
1643
    my $flagsrequired = shift;
1722
    my $params        = shift;
1644
    my $params        = shift;
1723
1645
1724
    my $remote_addr = $params->{remote_addr} || $ENV{REMOTE_ADDR};
1646
    my $remote_addr = $params->{remote_addr} || $ENV{REMOTE_ADDR};
1725
    my $dbh     = C4::Context->dbh;
1726
    my $timeout = _timeout_syspref();
1727
1647
1728
    unless ( C4::Context->preference('Version') ) {
1648
    unless ( C4::Context->preference('Version') ) {
1729
1649
Lines 1740-1766 sub check_cookie_auth { Link Here
1740
        return ( "maintenance", undef );
1660
        return ( "maintenance", undef );
1741
    }
1661
    }
1742
1662
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
1663
    # see if we have a valid session cookie already
1751
    # however, if a userid parameter is present (i.e., from
1664
    # however, if a userid parameter is present (i.e., from
1752
    # a form submission, assume that any current cookie
1665
    # a form submission, assume that any current cookie
1753
    # is to be ignored
1666
    # is to be ignored
1754
    unless ( defined $cookie and $cookie ) {
1667
    unless ( defined $sessionID and $sessionID ) {
1755
        return ( "failed", undef );
1668
        return ( "failed", undef );
1756
    }
1669
    }
1757
    my $sessionID = $cookie;
1758
    my $session   = get_session($sessionID);
1670
    my $session   = get_session($sessionID);
1759
    C4::Context->_new_userenv($sessionID);
1671
    C4::Context->_new_userenv($sessionID);
1760
    if ($session) {
1672
    if ($session) {
1761
        C4::Context->interface($session->param('interface'));
1673
        C4::Context->interface($session->param('interface'));
1762
        C4::Context->set_userenv(
1674
        C4::Context->set_userenv(
1763
            $session->param('number'),       $session->param('id'),
1675
            $session->param('number'),       $session->param('id') // '',
1764
            $session->param('cardnumber'),   $session->param('firstname'),
1676
            $session->param('cardnumber'),   $session->param('firstname'),
1765
            $session->param('surname'),      $session->param('branch'),
1677
            $session->param('surname'),      $session->param('branch'),
1766
            $session->param('branchname'),   $session->param('flags'),
1678
            $session->param('branchname'),   $session->param('flags'),
Lines 1769-1785 sub check_cookie_auth { Link Here
1769
            $session->param('register_id'),  $session->param('register_name')
1681
            $session->param('register_id'),  $session->param('register_name')
1770
        );
1682
        );
1771
1683
1684
        my $userid   = $session->param('id');
1772
        my $ip       = $session->param('ip');
1685
        my $ip       = $session->param('ip');
1773
        my $lasttime = $session->param('lasttime');
1686
        my $lasttime = $session->param('lasttime');
1774
        my $userid   = $session->param('id');
1687
        my $timeout = _timeout_syspref();
1775
        if ( $lasttime < time() - $timeout ) {
1688
1689
        if ( !$lasttime || ( $lasttime < time() - $timeout ) ) {
1776
1690
1777
            # time out
1691
            # time out
1778
            $session->delete();
1692
            $session->delete();
1779
            $session->flush;
1693
            $session->flush;
1780
            C4::Context->_unset_userenv($sessionID);
1694
            C4::Context->_unset_userenv($sessionID);
1781
            $userid    = undef;
1782
            $sessionID = undef;
1783
            return ("expired", undef);
1695
            return ("expired", undef);
1784
        } elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $remote_addr ) {
1696
        } elsif ( C4::Context->preference('SessionRestrictionByIP') && $ip ne $remote_addr ) {
1785
1697
Lines 1787-1806 sub check_cookie_auth { Link Here
1787
            $session->delete();
1699
            $session->delete();
1788
            $session->flush;
1700
            $session->flush;
1789
            C4::Context->_unset_userenv($sessionID);
1701
            C4::Context->_unset_userenv($sessionID);
1790
            $userid    = undef;
1702
            return ( "restricted", undef, { old_ip => $ip, new_ip => $remote_addr});
1791
            $sessionID = undef;
1792
            return ( "expired", undef );
1793
        } else {
1703
        } else {
1794
            $session->param( 'lasttime', time() );
1704
            $session->param( 'lasttime', time() );
1795
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1705
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1796
            if ($flags) {
1706
            if ($flags) {
1797
                return ( "ok", $sessionID );
1707
                return ( "ok", $session );
1798
            } else {
1708
            } else {
1799
                $session->delete();
1709
                $session->delete();
1800
                $session->flush;
1710
                $session->flush;
1801
                C4::Context->_unset_userenv($sessionID);
1711
                C4::Context->_unset_userenv($sessionID);
1802
                $userid    = undef;
1803
                $sessionID = undef;
1804
                return ( "failed", undef );
1712
                return ( "failed", undef );
1805
            }
1713
            }
1806
        }
1714
        }
1807
- 

Return to bug 28785