X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=C4%2FAuth.pm;h=d73edaf5f7cda2c06bd1acfa082b1f2bdb2d921f;hb=0476b6da325f8aaa8ebda4bc5352d96f3e5b386a;hp=811151b6282f854e8471ba8f9edd11d2b302180f;hpb=327b6c6ce31942963efcc03d5aea2981250360f2;p=koha.git diff --git a/C4/Auth.pm b/C4/Auth.pm index 811151b628..d73edaf5f7 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -19,9 +19,8 @@ package C4::Auth; use strict; use warnings; - use Digest::MD5 qw(md5_base64); -use Storable qw(thaw freeze); +use JSON qw/encode_json decode_json/; use URI::Escape; use CGI::Session; @@ -30,6 +29,7 @@ use C4::Context; use C4::Templates; # to get the template use C4::Branch; # GetBranches use C4::VirtualShelves; +use Koha::AuthUtils qw(hash_password); use POSIX qw/strftime/; use List::MoreUtils qw/ any /; @@ -47,7 +47,10 @@ BEGIN { $debug = $ENV{DEBUG}; @ISA = qw(Exporter); @EXPORT = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions); - @EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &get_all_subpermissions &get_user_subpermissions); + @EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &checkpw_internal &checkpw_hash + &get_all_subpermissions &get_user_subpermissions + ParseSearchHistoryCookie + ); %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] ); $ldap = C4::Context->config('useldapserver') || 0; $cas = C4::Context->preference('casAuthentication'); @@ -132,10 +135,17 @@ VALUES ( ?, ?, ?, ?, ?, EOQ sub get_template_and_user { + my $in = shift; - my $template = - C4::Templates::gettemplate( $in->{'template_name'}, $in->{'type'}, $in->{'query'}, $in->{'is_plugin'} ); my ( $user, $cookie, $sessionID, $flags ); + + my $template = C4::Templates::gettemplate( + $in->{'template_name'}, + $in->{'type'}, + $in->{'query'}, + $in->{'is_plugin'} + ); + if ( $in->{'template_name'} !~m/maintenance/ ) { ( $user, $cookie, $sessionID, $flags ) = checkauth( $in->{'query'}, @@ -204,6 +214,7 @@ sub get_template_and_user { $template->param( CAN_user_reports => 1 ); $template->param( CAN_user_staffaccess => 1 ); $template->param( CAN_user_plugins => 1 ); + $template->param( CAN_user_coursereserves => 1 ); foreach my $module (keys %$all_perms) { foreach my $subperm (keys %{ $all_perms->{$module} }) { $template->param( "CAN_user_${module}_${subperm}" => 1 ); @@ -251,29 +262,25 @@ sub get_template_and_user { # And if there's a cookie with searches performed when the user was not logged in, # we add them to the logged-in search history - my $searchcookie = $in->{'query'}->cookie('KohaOpacRecentSearches'); - if ($searchcookie){ - $searchcookie = uri_unescape($searchcookie); - my @recentSearches = @{thaw($searchcookie) || []}; - if (@recentSearches) { - my $sth = $dbh->prepare($SEARCH_HISTORY_INSERT_SQL); - $sth->execute( $borrowernumber, - $in->{'query'}->cookie("CGISESSID"), - $_->{'query_desc'}, - $_->{'query_cgi'}, - $_->{'total'}, - $_->{'time'}, - ) foreach @recentSearches; - - # And then, delete the cookie's content - my $newsearchcookie = $in->{'query'}->cookie( - -name => 'KohaOpacRecentSearches', - -value => freeze([]), - -HttpOnly => 1, - -expires => '' - ); - $cookie = [$cookie, $newsearchcookie]; - } + my @recentSearches = ParseSearchHistoryCookie($in->{'query'}); + if (@recentSearches) { + my $sth = $dbh->prepare($SEARCH_HISTORY_INSERT_SQL); + $sth->execute( $borrowernumber, + $in->{'query'}->cookie("CGISESSID"), + $_->{'query_desc'}, + $_->{'query_cgi'}, + $_->{'total'}, + $_->{'time'}, + ) foreach @recentSearches; + + # And then, delete the cookie's content + my $newsearchcookie = $in->{'query'}->cookie( + -name => 'KohaOpacRecentSearches', + -value => encode_json([]), + -HttpOnly => 1, + -expires => '' + ); + $cookie = [$cookie, $newsearchcookie]; } } } @@ -282,36 +289,22 @@ sub get_template_and_user { $template->param( sessionID => $sessionID ); my ($total, $pubshelves) = C4::VirtualShelves::GetSomeShelfNames(undef, 'MASTHEAD'); - $template->param( - pubshelves => $total->{pubtotal}, - pubshelvesloop => $pubshelves, - ); + $template->param( + pubshelves => $total->{pubtotal}, + pubshelvesloop => $pubshelves, + ); } # Anonymous opac search history # If opac search history is enabled and at least one search has already been performed if (C4::Context->preference('EnableOpacSearchHistory')) { - my $searchcookie = $in->{'query'}->cookie('KohaOpacRecentSearches'); - if ($searchcookie){ - $searchcookie = uri_unescape($searchcookie); - my @recentSearches = @{thaw($searchcookie) || []}; - # We show the link in opac - if (@recentSearches) { - $template->param(ShowOpacRecentSearchLink => 1); - } + my @recentSearches = ParseSearchHistoryCookie($in->{'query'}); + if (@recentSearches) { + $template->param(ShowOpacRecentSearchLink => 1); } } if(C4::Context->preference('dateformat')){ - $template->param( dateformat => C4::Context->preference('dateformat') ); - if(C4::Context->preference('dateformat') eq "metric"){ - $template->param(dateformat_metric => 1); - } elsif(C4::Context->preference('dateformat') eq "us"){ - $template->param(dateformat_us => 1); - } else { - $template->param(dateformat_iso => 1); - } - } else { - $template->param(dateformat_iso => 1); + $template->param(dateformat => C4::Context->preference('dateformat')) } # these template parameters are set the same regardless of $in->{'type'} @@ -346,7 +339,7 @@ sub get_template_and_user { CalendarFirstDayOfWeek => (C4::Context->preference("CalendarFirstDayOfWeek") eq "Sunday")?0:1, CircAutocompl => C4::Context->preference("CircAutocompl"), FRBRizeEditions => C4::Context->preference("FRBRizeEditions"), - IndependantBranches => C4::Context->preference("IndependantBranches"), + IndependentBranches => C4::Context->preference("IndependentBranches"), IntranetNav => C4::Context->preference("IntranetNav"), IntranetmainUserblock => C4::Context->preference("IntranetmainUserblock"), LibraryName => C4::Context->preference("LibraryName"), @@ -369,6 +362,7 @@ sub get_template_and_user { AllowMultipleCovers => C4::Context->preference('AllowMultipleCovers'), EnableBorrowerFiles => C4::Context->preference('EnableBorrowerFiles'), UseKohaPlugins => C4::Context->preference('UseKohaPlugins'), + UseCourseReserves => C4::Context->preference("UseCourseReserves"), ); } else { @@ -398,7 +392,7 @@ sub get_template_and_user { AnonSuggestions => "" . C4::Context->preference("AnonSuggestions"), AuthorisedValueImages => C4::Context->preference("AuthorisedValueImages"), BranchesLoop => GetBranchesLoop($opac_name), - BranchCategoriesLoop => GetBranchCategories( undef, undef, 1, $opac_name ), + BranchCategoriesLoop => GetBranchCategories( 'searchdomain', 1, $opac_name ), CalendarFirstDayOfWeek => (C4::Context->preference("CalendarFirstDayOfWeek") eq "Sunday")?0:1, LibraryName => "" . C4::Context->preference("LibraryName"), LibraryNameTitle => "" . $LibraryNameTitle, @@ -408,7 +402,6 @@ sub get_template_and_user { OpacHighlightedWords => C4::Context->preference("OpacHighlightedWords"), OPACItemHolds => C4::Context->preference("OPACItemHolds"), OPACShelfBrowser => "". C4::Context->preference("OPACShelfBrowser"), - OpacShowRecentComments => C4::Context->preference("OpacShowRecentComments"), OPACURLOpenInNewWindow => "" . C4::Context->preference("OPACURLOpenInNewWindow"), OPACUserCSS => "". C4::Context->preference("OPACUserCSS"), OPACMobileUserCSS => "". C4::Context->preference("OPACMobileUserCSS"), @@ -448,13 +441,11 @@ sub get_template_and_user { opacsmallimage => "" . C4::Context->preference("opacsmallimage"), opacuserjs => C4::Context->preference("opacuserjs"), opacuserlogin => "" . C4::Context->preference("opacuserlogin"), - reviewson => C4::Context->preference("reviewson"), ShowReviewer => C4::Context->preference("ShowReviewer"), ShowReviewerPhoto => C4::Context->preference("ShowReviewerPhoto"), suggestion => "" . C4::Context->preference("suggestion"), virtualshelves => "" . C4::Context->preference("virtualshelves"), OPACSerialIssueDisplayCount => C4::Context->preference("OPACSerialIssueDisplayCount"), - OpacAddMastheadLibraryPulldown => C4::Context->preference("OpacAddMastheadLibraryPulldown"), OPACXSLTDetailsDisplay => C4::Context->preference("OPACXSLTDetailsDisplay"), OPACXSLTResultsDisplay => C4::Context->preference("OPACXSLTResultsDisplay"), SyndeticsClientCode => C4::Context->preference("SyndeticsClientCode"), @@ -476,6 +467,20 @@ sub get_template_and_user { $template->param(OpacPublic => '1') if ($user || C4::Context->preference("OpacPublic")); } + + # Check if we were asked using parameters to force a specific language + if ( defined $in->{'query'}->param('language') ) { + # Extract the language, let C4::Templates::getlanguage choose + # what to do + my $language = C4::Templates::getlanguage($in->{'query'},$in->{'type'}); + my $languagecookie = C4::Templates::getlanguagecookie($in->{'query'},$language); + if ( ref $cookie eq 'ARRAY' ) { + push @{ $cookie }, $languagecookie; + } else { + $cookie = [$cookie, $languagecookie]; + } + } + return ( $template, $borrowernumber, $cookie, $flags); } @@ -881,7 +886,7 @@ sub checkauth { $branchname = GetBranchName($branchcode); } my $branches = GetBranches(); - if (C4::Context->boolean_preference('IndependantBranches') && C4::Context->boolean_preference('Autolocation')){ + if (C4::Context->boolean_preference('IndependentBranches') && C4::Context->boolean_preference('Autolocation')){ # we have to check they are coming from the right ip range my $domain = $branches->{$branchcode}->{'branchip'}; if ($ip !~ /^$domain/){ @@ -990,6 +995,10 @@ sub checkauth { push @inputs, { name => $name, value => $value }; } + my $LibraryNameTitle = C4::Context->preference("LibraryName"); + $LibraryNameTitle =~ s/<(?:\/?)(?:br|p)\s*(?:\/?)>/ /sgi; + $LibraryNameTitle =~ s/<(?:[^<>'"]|'(?:[^']*)'|"(?:[^"]*)")*>//sg; + my $template_name = ( $type eq 'opac' ) ? 'opac-auth.tmpl' : 'auth.tmpl'; my $template = C4::Templates::gettemplate($template_name, $type, $query ); $template->param( @@ -1001,7 +1010,8 @@ sub checkauth { casAuthentication => C4::Context->preference("casAuthentication"), suggestion => C4::Context->preference("suggestion"), virtualshelves => C4::Context->preference("virtualshelves"), - LibraryName => C4::Context->preference("LibraryName"), + LibraryName => "" . C4::Context->preference("LibraryName"), + LibraryNameTitle => "" . $LibraryNameTitle, opacuserlogin => C4::Context->preference("opacuserlogin"), OpacNav => C4::Context->preference("OpacNav"), OpacNavRight => C4::Context->preference("OpacNavRight"), @@ -1026,17 +1036,26 @@ sub checkauth { IntranetNav => C4::Context->preference("IntranetNav"), IntranetFavicon => C4::Context->preference("IntranetFavicon"), intranetuserjs => C4::Context->preference("intranetuserjs"), - IndependantBranches=> C4::Context->preference("IndependantBranches"), + IndependentBranches=> C4::Context->preference("IndependentBranches"), AutoLocation => C4::Context->preference("AutoLocation"), wrongip => $info{'wrongip'}, PatronSelfRegistration => C4::Context->preference("PatronSelfRegistration"), PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"), persona => C4::Context->preference("Persona"), + opac_css_override => $ENV{'OPAC_CSS_OVERRIDE'}, ); $template->param( OpacPublic => C4::Context->preference("OpacPublic")); $template->param( loginprompt => 1 ) unless $info{'nopermission'}; + if($type eq 'opac'){ + my ($total, $pubshelves) = C4::VirtualShelves::GetSomeShelfNames(undef, 'MASTHEAD'); + $template->param( + pubshelves => $total->{pubtotal}, + pubshelvesloop => $pubshelves, + ); + } + if ($cas) { # Is authentication against multiple CAS servers enabled? @@ -1066,10 +1085,14 @@ sub checkauth { LibraryName => C4::Context->preference("LibraryName"), ); $template->param( %info ); - - require C4::Output; - C4::Output::output_html_with_http_headers( $query, $cookie, - $template->output); +# $cookie = $query->cookie(CGISESSID => $session->id +# ); + print $query->header( + -type => 'text/html', + -charset => 'utf-8', + -cookie => $cookie + ), + $template->output; safe_exit; } @@ -1465,8 +1488,8 @@ sub get_session { } sub checkpw { - my ( $dbh, $userid, $password, $query ) = @_; + if ($ldap) { $debug and print STDERR "## checkpw - checking LDAP\n"; my ($retval,$retcard,$retuserid) = checkpw_ldap(@_); # EXTERNAL AUTH @@ -1476,23 +1499,29 @@ sub checkpw { if ($cas && $query && $query->param('ticket')) { $debug and print STDERR "## checkpw - checking CAS\n"; # In case of a CAS authentication, we use the ticket instead of the password - my $ticket = $query->param('ticket'); + my $ticket = $query->param('ticket'); my ($retval,$retcard,$retuserid) = checkpw_cas($dbh, $ticket, $query); # EXTERNAL AUTH ($retval) and return ($retval,$retcard,$retuserid); - return 0; + return 0; } - # INTERNAL AUTH + return checkpw_internal(@_) +} + +sub checkpw_internal { + my ( $dbh, $userid, $password ) = @_; + my $sth = $dbh->prepare( "select password,cardnumber,borrowernumber,userid,firstname,surname,branchcode,flags from borrowers where userid=?" ); $sth->execute($userid); if ( $sth->rows ) { - my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname, + my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname, $surname, $branchcode, $flags ) = $sth->fetchrow; - if ( md5_base64($password) eq $md5password and $md5password ne "!") { + + if ( checkpw_hash($password, $stored_hash) ) { C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber, $firstname, $surname, $branchcode, $flags ); @@ -1505,10 +1534,11 @@ sub checkpw { ); $sth->execute($userid); if ( $sth->rows ) { - my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname, + my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname, $surname, $branchcode, $flags ) = $sth->fetchrow; - if ( md5_base64($password) eq $md5password ) { + + if ( checkpw_hash($password, $stored_hash) ) { C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber, $firstname, $surname, $branchcode, $flags ); @@ -1535,6 +1565,21 @@ sub checkpw { return 0; } +sub checkpw_hash { + my ( $password, $stored_hash ) = @_; + + return if $stored_hash eq '!'; + + # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5 + my $hash; + if ( substr($stored_hash,0,2) eq '$2') { + $hash = hash_password($password, $stored_hash); + } else { + $hash = md5_base64($password); + } + return $hash eq $stored_hash; +} + =head2 getuserflags my $authflags = getuserflags($flags, $userid, [$dbh]); @@ -1715,6 +1760,15 @@ sub getborrowernumber { return 0; } +sub ParseSearchHistoryCookie { + my $input = shift; + my $search_cookie = $input->cookie('KohaOpacRecentSearches'); + return () unless $search_cookie; + my $obj = eval { decode_json(uri_unescape($search_cookie)) }; + return () unless defined $obj; + return () unless ref $obj eq 'ARRAY'; + return @{ $obj }; +} END { } # module clean-up code here (global destructor) 1; @@ -1726,6 +1780,8 @@ CGI(3) C4::Output(3) +Crypt::Eksblowfish::Bcrypt(3) + Digest::MD5(3) =cut