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

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

Return to bug 28785