Package: liblemonldap-ng-portal-perl
Severity: grave
Tags: security upstream patch
Justification: user security hole
Forwarded: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/1742
Found: 1.9.7-3

Hi all,

during an internal audit, one of lemonldap-ngi's developers discovered an
attack vector. It opens 3 security issues:
 - [high] for 2.0.0 ≤ version < 2.0.4: when CSRF tokens are
   enabled (default) and tokens are stored in session DB (not default,
   used with poor load-balancers), the token can be used to open an
   anonymous short-life session (2mn). It allows one to access to all
   aplications without additional rules
 - [high] for every versions < 2.0.4 or 1.9.19 when SAML/OIDC tokens are
   stored in sessions DB (not default), tokens can be used to have an
   anonymous session
 - [low] for every versions < 2.0.4 or 1.9.19: when self-registration
   is allowed, mail token can be used to have an anonymous session.

Attachements:
 - lemonldap-ng_2.0.2+ds-6.debdiff: fix for stretch
 - lemonldap-ng_2.0.2+ds-7.patch: patch for Buster. It includes 3 new
   upstream tests to prove that vulnerabilities are fixed
 - llng-1742-test.sh: a small tool that can be used to test an existing
   2.0.x installation

This issue also affects Ubuntu-19.04 which includes lemonldap-ng_2.0.2+ds-6.

Cheers,
Xavier

Description: Fix for CVE XXXX
 When CSRF is enabled (default) and tokens are stored in session database
 (not default, used for poor load balancers), a short-life session can be
 created without being authentified.
 This patch fixes also a low level vulnerability on self-register (same vector,
 see https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/1743)
 .
 This patch adds also 2 new upstream tests to prove that issues are fixed.
 .
 https://security-tracker.debian.org/tracker/CVE-2019-12046
Author: Xavier Guimard <y...@debian.org>
Origin: upstream, https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/1742
Bug: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/1742
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: not-needed
Last-Update: 2019-05-12

--- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Apache/Session/REST.pm
+++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Apache/Session/REST.pm
@@ -21,7 +21,7 @@
         modified => 0,
     };
     foreach (
-        qw(baseUrl user password realm localStorage localStorageOptions lwpOpts lwpSslOpts)
+        qw(baseUrl user password realm localStorage localStorageOptions lwpOpts lwpSslOpts kind)
       )
     {
         $self->{$_} = $args->{$_};
@@ -116,8 +116,13 @@
 
 sub getJson {
     my $self = shift;
-    my $url  = shift;
-    my $resp = $self->ua->get( $self->base . $url, @_ );
+    my $id   = shift;
+    my $resp = $self->ua->get(
+        $self->base
+          . $id
+          . ( $self->{kind} ne 'SSO' ? "?kind=$self->{kind}" : '' ),
+        @_
+    );
     if ( $resp->is_success ) {
         my $res;
         eval { $res = from_json( $resp->content, { allow_nonref => 1 } ) };
--- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session.pm
+++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session.pm
@@ -139,6 +139,14 @@
 
     # Load session data into object
     if ($data) {
+        if ( $self->kind and $data->{_session_kind} ) {
+            unless ( $data->{_session_kind} eq $self->kind ) {
+                $self->error(
+                    "Session kind mismatch : $data->{_session_kind} is not "
+                      . $self->kind );
+                return undef;
+            }
+        }
         $self->_save_data($data);
         $self->kind( $data->{_session_kind} );
         $self->id( $data->{_session_id} );
@@ -158,7 +166,7 @@
         if ( $self->storageModule =~ /^Lemonldap::NG::Common::Apache::Session/ )
         {
             tie %h, $self->storageModule, $self->id,
-              { %{ $self->options }, %$options };
+              { %{ $self->options }, %$options, kind => $self->kind };
         }
         else {
             tie %h, 'Lemonldap::NG::Common::Apache::Session', $self->id,
--- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session/REST.pm
+++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session/REST.pm
@@ -248,7 +248,7 @@
               Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheOptions},
             id    => $id,
             force => $force,
-            kind  => $mod->{kind},
+            ( $id ? () : ( kind => $mod->{kind} ) ),
             ( $info ? ( info => $info ) : () ),
         }
     );
@@ -271,6 +271,9 @@
         $self->error('Unknown (or unconfigured) session type');
         return ();
     }
+    if ( my $kind = $req->params('kind') ) {
+        $m->{kind} = $kind;
+    }
     return $m;
 }
 
--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/OneTimeToken.pm
+++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/OneTimeToken.pm
@@ -5,7 +5,7 @@
 use JSON qw(from_json to_json);
 use Crypt::URandom;
 
-our $VERSION = '2.0.2';
+our $VERSION = '2.0.4';
 
 extends 'Lemonldap::NG::Common::Module';
 
@@ -76,7 +76,8 @@
     else {
 
         # Create a new session
-        my $tsession = $self->p->getApacheSession( undef, info => $infos );
+        my $tsession =
+          $self->p->getApacheSession( undef, info => $infos, kind => 'TOKEN' );
         $self->logger->debug("Token $tsession->{id} created");
         return $tsession->id;
     }
@@ -108,7 +109,7 @@
     else {
 
         # Get token session
-        my $tsession = $self->p->getApacheSession($id);
+        my $tsession = $self->p->getApacheSession( $id, kind => 'TOKEN' );
         unless ($tsession) {
             $self->logger->notice("Bad (or expired) token $id");
             return undef;
@@ -133,7 +134,11 @@
         return $id;
     }
     else {
-        $self->p->getApacheSession( $id, $k => $v );
+        $self->p->getApacheSession(
+            $id,
+            kind => "TOKEN",
+            info => { $k => $v }
+        );
         return $id;
     }
 }
--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Remote.pm
+++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Remote.pm
@@ -50,7 +50,7 @@
                 cacheModule        => $self->conf->{localSessionStorage},
                 cacheModuleOptions => $self->conf->{localSessionStorageOptions},
                 id                 => $rId,
-                kind               => "REMOTE",
+                kind               => "SSO",
             }
         );
 
--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm
+++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm
@@ -232,7 +232,7 @@
 
     # Browse found sessions to check if it's a mail session
     foreach my $id ( keys %$sessions ) {
-        my $mailSession = $self->p->getApacheSession($id);
+        my $mailSession = $self->p->getApacheSession($id, kind => 'TOKEN');
         next unless ($mailSession);
         return $mailSession if ( $mailSession->data->{_type} =~ /^mail$/ );
     }
@@ -257,7 +257,7 @@
 
     # Browse found sessions to check if it's a register session
     foreach my $id ( keys %$sessions ) {
-        my $registerSession = $self->p->getApacheSession($id);
+        my $registerSession = $self->p->getApacheSession($id, kind => 'TOKEN');
         next unless ($registerSession);
         return $id
           if (  $registerSession->data->{_type}
--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm
+++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm
@@ -318,7 +318,7 @@
 # If $id is set to undef or if $args{force} is true, return a new session.
 sub getApacheSession {
     my ( $self, $id, %args ) = @_;
-    $args{kind} ||= "SSO";
+    $args{kind} //= "SSO";
     if ($id) {
         $self->logger->debug("Try to get $args{kind} session $id");
     }
--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/CDA.pm
+++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/CDA.pm
@@ -31,33 +31,34 @@
         $self->logger->debug('CDA request');
 
         # Create CDA session
-        if ( my $cdaSession =
-            $self->p->getApacheSession( undef, kind => "CDA" ) )
-        {
-            my $cdaInfos = { '_utime' => time };
-            if ( $self->{conf}->{securedCookie} < 2 or $ssl ) {
-                $cdaInfos->{cookie_value} = $req->id;
-                $cdaInfos->{cookie_name}  = $self->{conf}->{cookieName};
-            }
-            else {
-                $cdaInfos->{cookie_value} =
-                  $req->{sessionInfo}->{_httpSession};
-                $cdaInfos->{cookie_name} = $self->{conf}->{cookieName} . "http";
-            }
-
-            $self->p->updateSession( $req, $cdaInfos, $cdaSession->id );
-
-            $req->{urldc} .=
-                ( $urldc =~ /\?/ ? '&' : '?' )
-              . $self->{conf}->{cookieName} . "cda="
-              . $cdaSession->id;
-
-            $self->logger->debug( "CDA redirection to " . $req->{urldc} );
+        my $cdaInfos = { '_utime' => time };
+        if ( $self->{conf}->{securedCookie} < 2 or $ssl ) {
+            $cdaInfos->{cookie_value} = $req->id;
+            $cdaInfos->{cookie_name}  = $self->{conf}->{cookieName};
         }
         else {
+            $cdaInfos->{cookie_value} =
+              $req->{sessionInfo}->{_httpSession};
+            $cdaInfos->{cookie_name} = $self->{conf}->{cookieName} . "http";
+        }
+
+        my $cdaSession =
+          $self->p->getApacheSession( undef, kind => "CDA", info => $cdaInfos );
+        unless ($cdaSession) {
             $self->logger->error("Unable to create CDA session");
             return PE_APACHESESSIONERROR;
         }
+
+        # We are about to redirect the user to the CDA application,
+        # dismiss any previously stored redirections (#1650)
+        delete $req->{pdata}->{_url};
+
+        $req->{urldc} .=
+            ( $urldc =~ /\?/ ? '&' : '?' )
+          . $self->{conf}->{cookieName} . "cda="
+          . $cdaSession->id;
+
+        $self->logger->debug( "CDA redirection to " . $req->{urldc} );
     }
     PE_OK;
 }
--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm
+++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm
@@ -112,7 +112,7 @@
         $self->logger->debug( "Token given for password reset: " . $mailToken );
 
         # Check if token is valid
-        my $mailSession = $self->p->getApacheSession($mailToken);
+        my $mailSession = $self->p->getApacheSession($mailToken, kind => 'TOKEN');
         unless ($mailSession) {
             $self->userLogger->warn('Bad reset token');
             return PE_BADMAILTOKEN;
@@ -251,7 +251,7 @@
         $infos->{_pdata} = $req->pdata;
 
         # create session
-        $mailSession = $self->p->getApacheSession( undef, info => $infos );
+        $mailSession = $self->p->getApacheSession( undef, kind => 'TOKEN', info => $infos );
 
         $req->id( $mailSession->id );
     }
--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/SOAPServer.pm
+++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/SOAPServer.pm
@@ -272,7 +272,7 @@
     my ( $self, $req, $id ) = @_;
     die 'id is required' unless ($id);
 
-    my $session = $self->p->getApacheSession($id);
+    my $session = $self->p->getApacheSession( $id, kind => '' );
 
     my @tmp = ();
     unless ($session) {
--- /dev/null
+++ b/lemonldap-ng-portal/t/41-Token-Global-Storage.t
@@ -0,0 +1,84 @@
+use Test::More;
+use strict;
+use IO::String;
+
+require 't/test-lib.pm';
+
+my $res;
+
+my $client = LLNG::Manager::Test->new( {
+        ini => {
+            logLevel              => 'error',
+            useSafeJail           => 1,
+            requireToken          => '"Bad rule"',
+            tokenUseGlobalStorage => 1,
+        }
+    }
+);
+
+# Test normal first access
+# ------------------------
+ok( $res = $client->_get( '/', accept => 'text/html' ), 'Unauth request' );
+count(1);
+
+my ( $host, $url, $query ) = expectForm( $res, '#', undef, 'token' );
+ok( $query =~ /token=([^&]+)/, 'Token value' );
+count(1);
+my $token = $1;
+$query =~ "token=$token";
+
+# Try to auth without token
+ok(
+    $res = $client->_post(
+        '/',
+        IO::String->new('user=dwho&password=dwho'),
+        length => 23
+    ),
+    'Try to auth without token'
+);
+count(1);
+expectReject($res);
+
+# Try token as cookie value
+ok( $res = $client->_get( '/', cookie => "lemonldap=$token" ),
+    'Try token as cookie' );
+count(1);
+expectReject($res);
+
+# Try to auth with token
+$query .= '&user=dwho&password=dwho';
+ok(
+    $res =
+      $client->_post( '/', IO::String->new($query), length => length($query) ),
+    'Try to auth with token'
+);
+count(1);
+expectOK($res);
+my $id = expectCookie($res);
+
+# Verify auth
+ok( $res = $client->_get( '/', cookie => "lemonldap=$id" ), 'Verify auth' );
+count(1);
+expectOK($res);
+
+# Try to reuse the same token
+ok(
+    $res =
+      $client->_post( '/', IO::String->new($query), length => length($query) ),
+    'Try to reuse the same token'
+);
+expectReject($res);
+ok(
+    $res = $client->_post(
+        '/', IO::String->new($query),
+        length => length($query),
+        accept => 'text/html'
+    ),
+    'Verify that there is a new token'
+);
+expectForm( $res, '#', undef, 'token' );
+count(2);
+
+clean_sessions();
+
+done_testing( count() );
--- /dev/null
+++ b/lemonldap-ng-portal/t/42-Register-Security.t
@@ -0,0 +1,78 @@
+use Test::More;
+use strict;
+use IO::String;
+
+BEGIN {
+    eval {
+        require 't/test-lib.pm';
+        require 't/smtp.pm';
+    };
+}
+
+my $maintests = 5;
+my ( $res, $user, $pwd );
+
+SKIP: {
+    eval 'require Email::Sender::Simple';
+    if ($@) {
+        skip 'Missing dependencies', $maintests;
+    }
+
+    my $client = LLNG::Manager::Test->new( {
+            ini => {
+                logLevel                 => 'error',
+                useSafeJail              => 1,
+                portalDisplayRegister    => 1,
+                authentication           => 'Demo',
+                userDB                   => 'Same',
+                registerDB               => 'Demo',
+                captcha_register_enabled => 0,
+                tokenUseGlobalStorage => 1,
+            }
+        }
+    );
+
+    # Test normal first access
+    # ------------------------
+    ok(
+        $res = $client->_get( '/register', accept => 'text/html' ),
+        'Unauth request',
+    );
+    my ( $host, $url, $query ) =
+      expectForm( $res, '#', undef, 'firstname', 'lastname', 'mail' );
+
+    ok(
+        $res = $client->_post(
+            '/register',
+            IO::String->new(
+                'firstname=fôo&lastname=bar&mail=foobar%40badwolf.org'),
+            length => 53,
+            accept => 'text/html'
+        ),
+        'Ask to create account'
+    );
+    expectOK($res);
+
+    my $mail = mail();
+    ok( $mail =~ m#a href="http://auth.example.com/register\?(.*?)"#,
+        'Found register token' );
+    $query = $1;
+    ok( $query =~ /register_token=([^&]+)/, 'Found register_token' );
+    my $token = $1;
+
+    ok(
+        $res = $client->_get(
+            '/',
+            length => 23,
+            cookie => "lemonldap=$token",
+        ),
+        'Try to authenticate'
+    );
+    expectReject($res);
+}
+count($maintests);
+
+clean_sessions();
+
+done_testing( count() );
+
--- /dev/null
+++ b/lemonldap-ng-portal/t/77-2F-Mail-with-global-storage.t
@@ -0,0 +1,70 @@
+use Test::More;
+use strict;
+use IO::String;
+use Data::Dumper;
+
+require 't/test-lib.pm';
+require 't/smtp.pm';
+
+use_ok('Lemonldap::NG::Common::FormEncode');
+count(1);
+
+my $client = LLNG::Manager::Test->new( {
+        ini => {
+            logLevel         => 'error',
+            mail2fActivation => 1,
+            mail2fCodeRegex  => '\d{4}',
+            authentication   => 'Demo',
+            userDB           => 'Same',
+	    tokenUseGlobalStorage => 1,
+        }
+    }
+);
+
+# Try to authenticate
+# -------------------
+ok(
+    my $res = $client->_post(
+        '/',
+        IO::String->new('user=dwho&password=dwho'),
+        length => 23,
+        accept => 'text/html',
+    ),
+    'Auth query'
+);
+count(1);
+
+my ( $host, $url, $query ) =
+  expectForm( $res, undef, '/mail2fcheck', 'token', 'code' );
+
+ok(
+    $res->[2]->[0] =~
+qr%<input name="code" value="" class="form-control" id="extcode" trplaceholder="code" autocomplete="off" />%,
+    'Found EXTCODE input'
+) or print STDERR Dumper( $res->[2]->[0] );
+count(1);
+
+ok( mail() =~ m%<b>(\d{4})</b>%, 'Found 2F code in mail' )
+  or print STDERR Dumper( mail() );
+
+my $code = $1;
+count(1);
+
+$query =~ s/code=/code=${code}/;
+ok(
+    $res = $client->_post(
+        '/mail2fcheck',
+        IO::String->new($query),
+        length => length($query),
+        accept => 'text/html',
+    ),
+    'Post code'
+);
+count(1);
+my $id = expectCookie($res);
+$client->logout($id);
+
+clean_sessions();
+
+done_testing( count() );
+
--- a/lemonldap-ng-portal/MANIFEST
+++ b/lemonldap-ng-portal/MANIFEST
@@ -471,10 +471,12 @@
 t/40-Notifications-XML-Server.t
 t/41-Captcha.t
 t/41-Token.t
+t/41-Token-Global-Storage.t
 t/42-Register-Demo-with-captcha.t
 t/42-Register-Demo-with-token.t
 t/42-Register-Demo.t
 t/42-Register-LDAP.t
+t/42-Register-Security.t
 t/43-MailPasswordReset-Choice.t
 t/43-MailPasswordReset-DBI.t
 t/43-MailPasswordReset-LDAP.t
@@ -511,6 +513,7 @@
 t/76-2F-Ext-with-BruteForce.t
 t/76-2F-Ext-with-GrantSession.t
 t/76-2F-Ext-with-HISTORY.t
+t/77-2F-Mail-with-global-storage.t
 t/77-2F-Mail.t
 t/90-Translations.t
 t/99-pod.t

Attachment: llng-1742-test.sh
Description: application/shellscript

diff --git a/debian/changelog b/debian/changelog
index 08d4a00bc..63ba5aa3f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+lemonldap-ng (1.9.7-3+deb9u1) unstable; urgency=medium
+
+  * Add patch to fix token security (Closes: CVE-2019-12046)
+
+ -- Xavier Guimard <y...@debian.org>  Mon, 13 May 2019 18:51:54 +0200
+
 lemonldap-ng (1.9.7-3) unstable; urgency=medium
 
   * Remove unnecessary version dependency for lsb-base
diff --git a/debian/patches/CVE-2019-12046.patch 
b/debian/patches/CVE-2019-12046.patch
new file mode 100644
index 000000000..53662e3e4
--- /dev/null
+++ b/debian/patches/CVE-2019-12046.patch
@@ -0,0 +1,178 @@
+Description: Fix for CVE-2019-12046
+Author: Xavier Guimard <x.guim...@free.fr>
+Origin: upstream, https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/1743
+Bug: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/1743
+Forwarded: not-needed
+Last-Update: 2019-05-13
+
+--- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session.pm
++++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session.pm
+@@ -109,6 +109,12 @@
+ 
+     # Load session data into object
+     if ($data) {
++        if ( $self->kind ) {
++            unless ( $data->{_session_kind} eq $self->kind ) {
++                $self->error("Session kind mistmatch");
++                return undef;
++            }
++        }
+         $self->_save_data($data);
+         $self->kind( $data->{_session_kind} );
+         $self->id( $data->{_session_id} );
+--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/MailReset.pm
++++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/MailReset.pm
+@@ -115,7 +115,8 @@
+             'debug' );
+ 
+         # Get the corresponding session
+-        my $mailSession = $self->getApacheSession( $self->{mail_token} );
++        my $mailSession =
++          $self->getApacheSession( $self->{mail_token}, 1, undef, "mail" );
+ 
+         if ($mailSession) {
+             $self->{mail} = $mailSession->data->{user};
+@@ -215,7 +216,7 @@
+       if ( $self->{mail_token} or $self->getMailSession( $self->{mail} ) );
+ 
+     # Create a new session
+-    my $mailSession = $self->getApacheSession();
++    my $mailSession = $self->getApacheSession( undef, 1, undef, "mail" );
+ 
+     # Set _utime for session autoremove
+     # Use default session timeout and mail session timeout to compute it
+@@ -259,16 +260,15 @@
+     # Skip this step if user clicked on the confirmation link
+     return PE_OK if $self->{mail_token};
+ 
+-    # Check if confirmation mail has already been sent
+     my $mail_session = $self->getMailSession( $self->{mail} );
+-    $self->{mail_already_sent} = ( $mail_session and !$self->{id} ) ? 1 : 0;
+ 
+     # Read mail session to get creation and expiration dates
+     $self->{id} = $mail_session unless $self->{id};
+ 
+     $self->lmLog( "Mail session found: $mail_session", 'debug' );
+ 
+-    my $mailSession = $self->getApacheSession( $mail_session, 1 );
++    my $mailSession =
++      $self->getApacheSession( $mail_session, 1, undef, "mail" );
+     $self->{mailSessionTimeoutTimestamp} =
+       $mailSession->data->{mailSessionTimeoutTimestamp};
+     $self->{mailSessionStartTimestamp} =
+@@ -342,6 +342,9 @@
+     return PE_MAILERROR
+       unless $self->send_mail( $self->{mailAddress}, $subject, $body, $html );
+ 
++    # Save status
++    $mailSession->update( { "mail_already_sent" => 1 } );
++
+     PE_MAILCONFIRMOK;
+ }
+ 
+@@ -384,7 +387,8 @@
+     if ( $result == PE_PASSWORD_OK or $result == PE_OK ) {
+ 
+         # Get the corresponding session
+-        my $mailSession = $self->getApacheSession( $self->{mail_token} );
++        my $mailSession =
++          $self->getApacheSession( $self->{mail_token}, 1, undef, "mail" );
+ 
+         if ($mailSession) {
+ 
+--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Register.pm
++++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Register.pm
+@@ -107,8 +107,8 @@
+             'debug' );
+ 
+         # Get the corresponding session
+-        my $registerSession =
+-          $self->getApacheSession( $self->{register_token} );
++        my $registerSession = $self->getApacheSession( 
$self->{register_token},
++            1, undef, "register" );
+ 
+         if ( $registerSession && $registerSession->data ) {
+             $self->{registerInfo}->{mail} = $registerSession->data->{mail};
+@@ -223,7 +223,8 @@
+         or $self->getRegisterSession( $self->{registerInfo}->{mail} ) );
+ 
+     # Create a new session
+-    my $registerSession = $self->getApacheSession();
++    my $registerSession =
++      $self->getApacheSession( undef, 1, undef, "register" );
+ 
+     # Set _utime for session autoremove
+     # Use default session timeout and register session timeout to compute it
+@@ -267,17 +268,16 @@
+     # Skip this step if user clicked on the confirmation link
+     return PE_OK if $self->{register_token};
+ 
+-    # Check if confirmation mail has already been sent
+     my $register_session =
+       $self->getRegisterSession( $self->{registerInfo}->{mail} );
+-    $self->{mail_already_sent} = ( $register_session and !$self->{id} ) ? 1 : 
0;
+ 
+     # Read session to get creation and expiration dates
+     $self->{id} = $register_session unless $self->{id};
+ 
+     $self->lmLog( "Register session found: $register_session", 'debug' );
+ 
+-    my $registerSession = $self->getApacheSession( $register_session, 1 );
++    my $registerSession =
++      $self->getApacheSession( $register_session, 1, undef, "register" );
+     $self->{registerInfo}->{registerSessionTimeoutTimestamp} =
+       $registerSession->data->{registerSessionTimeoutTimestamp};
+     $self->{registerInfo}->{registerSessionStartTimestamp} =
+@@ -300,7 +300,9 @@
+     $self->{startMailTime} = strftime( "%H:%M",    localtime $startTimestamp 
);
+ 
+     # Ask if user want another confirmation email
+-    if ( $self->{mail_already_sent} and !$self->param('resendconfirmation') ) 
{
++    if ( $registerSession->data->{mail_already_sent}
++        and !$self->param('resendconfirmation') )
++    {
+         return PE_MAILCONFIRMATION_ALREADY_SENT;
+     }
+ 
+@@ -338,6 +340,9 @@
+       unless $self->send_mail( $self->{registerInfo}->{mail}, $subject, $body,
+         $html );
+ 
++    # Save status
++    $registerSession->update( { "mail_already_sent" => 1 } );
++
+     PE_MAILCONFIRMOK;
+ }
+ 
+@@ -384,8 +389,8 @@
+     if ( $result == PE_OK ) {
+ 
+         # Get the corresponding session
+-        my $registerSession =
+-          $self->getApacheSession( $self->{register_token} );
++        my $registerSession = $self->getApacheSession( 
$self->{register_token},
++            1, undef, "register" );
+ 
+         if ($registerSession) {
+ 
+--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_SMTP.pm
++++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_SMTP.pm
+@@ -143,7 +143,7 @@
+ 
+     # Browse found sessions to check if it's a mail session
+     foreach my $id ( keys %$sessions ) {
+-        my $mailSession = $self->getApacheSession( $id, 1 );
++        my $mailSession = $self->getApacheSession( $id, 1, undef, "mail" );
+         next unless ($mailSession);
+         return $id if ( $mailSession->data->{_type} =~ /^mail$/ );
+     }
+@@ -168,7 +168,8 @@
+ 
+     # Browse found sessions to check if it's a register session
+     foreach my $id ( keys %$sessions ) {
+-        my $registerSession = $self->getApacheSession( $id, 1 );
++        my $registerSession =
++          $self->getApacheSession( $id, 1, undef, "register" );
+         next unless ($registerSession);
+         return $id if ( $registerSession->data->{_type} =~ /^register$/ );
+     }
diff --git a/debian/patches/series b/debian/patches/series
index 661cd37e1..b13b6df06 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -2,3 +2,4 @@ javascript-path.patch
 avoid-modify-sources.patch
 replace-mouse-by-moose.patch
 Avoid-developer-tests.patch
+CVE-2019-12046.patch

Reply via email to