From d8bb17c3e1ecbf8906127024296ce07cba33f036 Mon Sep 17 00:00:00 2001
From: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Date: Thu, 24 Mar 2022 07:31:12 +0000
Subject: [PATCH] Bug 29915: Prevent bad cookie from corrupted session
Content-Type: text/plain; charset=utf-8

If there is deleted session info but no session->id, a wrong cookie
with empty name could be generated containing expired session id.

Test plan:
Run t/db_dependent/Auth.t
Login. Check cookies in browser.
Logout. Check cookies in browser.
Without this patch, you should see an invalid cookie.

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
---
 C4/Auth.pm            | 6 ++++--
 t/db_dependent/Auth.t | 9 ++++++++-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/C4/Auth.pm b/C4/Auth.pm
index 88dc23165f..5f217dcb12 100644
--- a/C4/Auth.pm
+++ b/C4/Auth.pm
@@ -958,7 +958,9 @@ sub checkauth {
 
     unless ( $userid ) {
         #we initiate a session prior to checking for a username to allow for anonymous sessions...
-        $session ||= get_session("") or die "Auth ERROR: Cannot get_session()";
+        if( !$session or !$sessionID ) { # if we cleared sessionID, we need a new session
+            $session = get_session() or die "Auth ERROR: Cannot get_session()";
+        }
 
         # Save anonymous search history in new session so it can be retrieved
         # by get_template_and_user to store it in user's search history after
@@ -1793,7 +1795,7 @@ sub get_session {
         $session = CGI::Session->load( $params->{dsn}, $sessionID, $params->{dsn_args} );
     } else {
         $session = CGI::Session->new( $params->{dsn}, $sessionID, $params->{dsn_args} );
-        # $session->flush;
+        $session->flush;
     }
     return $session;
 }
diff --git a/t/db_dependent/Auth.t b/t/db_dependent/Auth.t
index 199637f08c..8c7f82c666 100755
--- a/t/db_dependent/Auth.t
+++ b/t/db_dependent/Auth.t
@@ -547,7 +547,14 @@ subtest 'checkauth & check_cookie_auth' => sub {
 
     # Logging out!
     $cgi->param('logout.x', 1);
-    ( $userid, $cookie, $sessionID, $flags ) = C4::Auth::checkauth($cgi, 0, {catalogue => 1});
+    $cgi->delete( 'userid', 'password' );
+    {
+        local *STDOUT;
+        my $stdout;
+        open STDOUT, '>', \$stdout;
+        ( $userid, $cookie, $sessionID, $flags ) = C4::Auth::checkauth($cgi, 0, {catalogue => 1});
+        close STDOUT;
+    }
     is( $sessionID, undef );
     is( $ENV{"HTTP_COOKIE"}, "CGISESSID=$first_sessionID", 'HTTP_COOKIE not unset' );
     ( $auth_status, $session) = C4::Auth::check_cookie_auth( $first_sessionID, {catalogue => 1} );
-- 
2.20.1