Bug#1109159: bookworm-pu: package lemonldap-ng/2.16.1+ds-deb12u7

Yadd yadd at debian.org
Sat Jul 12 19:18:37 BST 2025


Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: lemonldap-ng at packages.debian.org, yadd at debian.org
Control: affects -1 + src:lemonldap-ng
User: release.debian.org at packages.debian.org
Usertags: pu

[ Reason ]
Lemonldap-NG community published a new LTS version: 2.16.6. The main
changed inported here are:
 * Fix sessions tablename when not default
 * Fix OpenID-Connect flow when user encountered an error on server side
 * Fix Kerberos JavaScript when used with "Choice"
 * Improve CORS check
 * Fix path_info

[ Impact ]
Some annonying bugs

[ Tests ]
New patches includes tests

[ Risks ]
Low risk, test coverage is good

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in (old)stable
  [X] the issue is verified as fixed in unstable

Best regards,
Xavier
-------------- next part --------------
diff --git a/debian/changelog b/debian/changelog
index a2a7ee804..aededc82a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+lemonldap-ng (2.16.1+ds-deb12u7) bookworm; urgency=medium
+
+  * Fix sessions tablename when not default
+  * Fix OpenID-Connect flow when user encountered an error on server side
+  * Fix Kerberos JavaScript when used with "Choice"
+  * Improve CORS check
+  * Fix path_info
+
+ -- Yadd <yadd at debian.org>  Sat, 12 Jul 2025 20:12:21 +0200
+
 lemonldap-ng (2.16.1+ds-deb12u6) bookworm-security; urgency=high
 
   * Fix XSS vulnerability in Choice module (Closes: CVE-2025-31510)
diff --git a/debian/patches/fix-bad-table-name.patch b/debian/patches/fix-bad-table-name.patch
new file mode 100644
index 000000000..d49b65114
--- /dev/null
+++ b/debian/patches/fix-bad-table-name.patch
@@ -0,0 +1,20 @@
+Description: fix fixed tablename
+Author: Yadd <yadd at debian.org>
+Origin: upstream, https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/commit/d9db2a6b
+Bug: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3405
+Forwarded: not-needed
+Applied-Upstream: 2.16.6, commit:25663e12
+Last-Update: 2025-07-12
+
+--- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Apache/Session.pm
++++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Apache/Session.pm
+@@ -212,7 +212,8 @@
+     my $dbh =
+       DBI->connect( $args->{DataSource}, $args->{UserName}, $args->{Password} )
+       or die("$!$@");
+-    my $sth = $dbh->prepare('SELECT id,a_session from sessions');
++    my $sth = $dbh->prepare(
++        'SELECT id,a_session from ' . ( $args->{TableName} || 'sessions' ) );
+     $sth->execute;
+     my %res;
+     while ( my @row = $sth->fetchrow_array ) {
diff --git a/debian/patches/fix-kerberos-js.patch b/debian/patches/fix-kerberos-js.patch
new file mode 100644
index 000000000..470de834b
--- /dev/null
+++ b/debian/patches/fix-kerberos-js.patch
@@ -0,0 +1,103 @@
+Description: make Kerberos module not submit form in case of error in choice menu
+Author: Yadd <yadd at debian.org>
+Origin: upstream, https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/merge_requests/752
+Bug: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3406
+Forwarded: not-needed
+Applied-Upstream: 2.16.6, commit:bc193ef9
+Last-Update: 2025-07-12
+
+--- a/lemonldap-ng-portal/site/coffee/kerberosChoice.coffee
++++ b/lemonldap-ng-portal/site/coffee/kerberosChoice.coffee
+@@ -16,5 +16,30 @@
+ 			$('#lformKerberos').submit()
+ 		# Case else, will display PE_BADCREDENTIALS or fallback to next auth
+ 		# backend
+-		error: () ->
+-			$('#lformKerberos').submit()
++		error: (xhr, status, _error) ->
++			e = jQuery.Event "kerberosFailure"
++			$(document).trigger e, [xhr, status, _error]
++
++			# Check if we are in a choice menu
++			authMenu = $('#authMenu')
++
++			# If this is a choice menu, don't submit form
++			if authMenu.length
++				msgBox = $('#errormsg')
++				msgBoxContent = '<div class="message message-negative' + ' alert alert-danger" role="alert">'
++				# If this is a regular Kerberos authentication error,
++				# display the appropriate error message
++				if _error.match /Unauthorized/i
++					msgBoxContent += '<span trmsg="5">' + translate('PE5') + '</span>'
++				# Display generic error message
++				else
++					msgBoxContent += '<span trmsg="24">' + translate('PE24') + '</span>'
++					# If this is an unexpected Kerberos error,
++					# display the error in console
++					console.error "Error while trying Kerberos authentication: ", _error
++				msgBoxContent += '</div>'
++				msgBox.html msgBoxContent
++			# If this is NOT a choice menu, submit form
++			else
++				if !e.isDefaultPrevented()
++					$('#lformKerberos').submit()
+--- a/lemonldap-ng-portal/site/htdocs/static/common/js/kerberosChoice.js
++++ b/lemonldap-ng-portal/site/htdocs/static/common/js/kerberosChoice.js
+@@ -1,21 +1,54 @@
+-// Generated by CoffeeScript 1.12.8
++// Generated by CoffeeScript 2.7.0
+ (function() {
++  // Launch Kerberos request
+   $(document).ready(function() {
+     return $.ajax(portal + '/authkrb', {
+       dataType: 'json',
++      // Called if browser can't find Kerberos ticket, will display
++      // PE_BADCREDENTIALS
+       statusCode: {
+         401: function() {
+           return $('#lformKerberos').submit();
+         }
+       },
++      // If request succeed cookie is set, posting form to get redirection
++      // or menu
+       success: function(data) {
+         if (data.ajax_auth_token) {
+           $('#lformKerberos').find('input[name="ajax_auth_token"]').attr("value", data.ajax_auth_token);
+         }
+         return $('#lformKerberos').submit();
+       },
+-      error: function() {
+-        return $('#lformKerberos').submit();
++      // Case else, will display PE_BADCREDENTIALS or fallback to next auth
++      // backend
++      error: function(xhr, status, _error) {
++        var authMenu, e, msgBox, msgBoxContent;
++        e = jQuery.Event("kerberosFailure");
++        $(document).trigger(e, [xhr, status, _error]);
++        // Check if we are in a choice menu
++        authMenu = $('#authMenu');
++        // If this is a choice menu, don't submit form
++        if (authMenu.length) {
++          msgBox = $('#errormsg');
++          msgBoxContent = '<div class="message message-negative' + ' alert alert-danger" role="alert">';
++          // If this is a regular Kerberos authentication error,
++          // display the appropriate error message
++          if (_error.match(/Unauthorized/i)) {
++            msgBoxContent += '<span trmsg="5">' + translate('PE5') + '</span>';
++          } else {
++            // Display generic error message
++            msgBoxContent += '<span trmsg="24">' + translate('PE24') + '</span>';
++            // If this is an unexpected Kerberos error,
++            // display the error in console
++            console.error("Error while trying Kerberos authentication: ", _error);
++          }
++          msgBoxContent += '</div>';
++          return msgBox.html(msgBoxContent);
++        } else {
++          if (!e.isDefaultPrevented()) {
++            return $('#lformKerberos').submit();
++          }
++        }
+       }
+     });
+   });
diff --git a/debian/patches/fix-oidc-fixed-server-in-case-of-error.patch b/debian/patches/fix-oidc-fixed-server-in-case-of-error.patch
new file mode 100644
index 000000000..06fa90df0
--- /dev/null
+++ b/debian/patches/fix-oidc-fixed-server-in-case-of-error.patch
@@ -0,0 +1,97 @@
+Description: fix "when Auth::OpenIDConnect returns an error, the user cannot try again"
+Author: Maxime Besson <maxime.besson at worteks.com>
+Origin: upstream, https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/merge_requests/762
+Bug: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3427
+Forwarded: not-needed
+Applied-Upstream: v2.16.6, commit:17cdbbed
+Reviewed-By: Yadd <yadd at debian.org>
+Last-Update: 2025-07-12
+
+--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/OpenIDConnect.pm
++++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/OpenIDConnect.pm
+@@ -102,7 +102,13 @@
+     my ( $self, $req ) = @_;
+ 
+     # Check callback
+-    if ( $req->param( $self->conf->{oidcRPCallbackGetParam} ) ) {
++    if ( $req->param( $self->conf->{oidcRPCallbackGetParam} )
++        and not $req->param('oidc_callback_processed') )
++    {
++        # This makes sure we don't go through the callback code when re-posting
++        # a login form
++        $self->p->setHiddenFormValue( $req, "oidc_callback_processed", "1", "",
++            0 );
+ 
+         $self->logger->debug(
+             'OpenIDConnect callback URI detected: ' . $req->uri );
+--- a/lemonldap-ng-portal/t/32-Auth-and-issuer-OIDC-authorization_code.t
++++ b/lemonldap-ng-portal/t/32-Auth-and-issuer-OIDC-authorization_code.t
+@@ -409,6 +409,68 @@
+ 
+ #print STDERR Dumper($res);
+ 
++# Test OIDC auth retry (#3427)
++ok(
++    $res = $rp->_get(
++        "/", accept => 'text/html',
++    ),
++    "Initiate login"
++);
++count(1);
++
++( $url, $query ) =
++  expectRedirection( $res, qr#http://auth.op.com(/oauth2/authorize)\?(.*)$# );
++
++my $state = do {
++    my $u = URI->new;
++    $u->query($query);
++    $u->query_param('state');
++};
++
++ok(
++    $res = $rp->_get(
++        "/",
++        query => {
++            openidconnectcallback => 1,
++            error                 => "canceled",
++            state                 => $state,
++        },
++        accept => 'text/html',
++    ),
++    "Return with error"
++);
++count(1);
++expectPortalError( $res, 106 );
++
++( $host, $url, $query ) =
++  expectForm( $res, '#', undef, 'oidc_callback_processed' );
++
++ok(
++    $res = $rp->_post(
++        "/", $query,
++        query => {
++            openidconnectcallback => 1,
++            error                 => "canceled",
++            state                 => $state,
++        },
++        accept => 'text/html',
++    ),
++    "Submit form again"
++);
++count(1);
++
++( $url, $query ) =
++  expectRedirection( $res, qr#http://auth.op.com(/oauth2/authorize)\?(.*)$# );
++
++my $new_state = do {
++    my $u = URI->new;
++    $u->query($query);
++    $u->query_param('state');
++};
++ok( $new_state, "New state was generated" );
++isnt( $new_state, $state, "New state is different than previous" );
++count(2);
++
+ clean_sessions();
+ done_testing( count() );
+ 
diff --git a/debian/patches/fix-path-info.patch b/debian/patches/fix-path-info.patch
new file mode 100644
index 000000000..5ce71207a
--- /dev/null
+++ b/debian/patches/fix-path-info.patch
@@ -0,0 +1,49 @@
+Description: fix path_info
+Author: Maxime Besson <maxime.besson at worteks.com>
+Origin: upstream, https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/merge_requests/763
+Bug: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3338
+Forwarded: not-needed
+Applied-Upstream: 2.16.6, commit:8dfc8be2
+Reviewed-By: Xavier Guimard <yadd at debian.org>
+Last-Update: 2025-07-12
+
+--- a/e2e-tests/llng-server.psgi
++++ b/e2e-tests/llng-server.psgi
+@@ -51,10 +51,13 @@
+     psgi => sub {
+         return sub {
+ 
+-            # Fix PATH_INFO when using Nginx with default uwsgi_params
+-            # See #2031
+-            ( $_[0]->{PATH_INFO} ) =
+-              $_[0]->{REQUEST_URI} =~ /^(?:\Q$_[0]->{SCRIPT_NAME}\E)?([^?]*)/;
++            # Reimplement split_pathinfo
++            if ( $_[0]->{SCRIPT_NAME}
++                and rindex( $_[0]->{PATH_INFO}, $_[0]->{SCRIPT_NAME}, 0 ) == 0 )
++            {
++                $_[0]->{PATH_INFO} =
++                  substr( $_[0]->{PATH_INFO}, length( $_[0]->{SCRIPT_NAME} ) );
++            }
+ 
+             my $script = $_[0]->{SCRIPT_FILENAME};
+             return $_apps{$script}->(@_) if ( $_apps{$script} );
+--- a/lemonldap-ng-handler/eg/llng-server.psgi
++++ b/lemonldap-ng-handler/eg/llng-server.psgi
+@@ -53,10 +53,13 @@
+     psgi => sub {
+         return sub {
+ 
+-            # Fix PATH_INFO when using Nginx with default uwsgi_params
+-            # See #2031
+-            ( $_[0]->{PATH_INFO} ) =
+-              $_[0]->{REQUEST_URI} =~ /^(?:\Q$_[0]->{SCRIPT_NAME}\E)?([^?]*)/;
++            # Reimplement split_pathinfo
++            if ( $_[0]->{SCRIPT_NAME}
++                and rindex( $_[0]->{PATH_INFO}, $_[0]->{SCRIPT_NAME}, 0 ) == 0 )
++            {
++                $_[0]->{PATH_INFO} =
++                  substr( $_[0]->{PATH_INFO}, length( $_[0]->{SCRIPT_NAME} ) );
++            }
+ 
+             my $script = $_[0]->{SCRIPT_FILENAME};
+             return $_apps{$script}->(@_) if ( $_apps{$script} );
diff --git a/debian/patches/improve-cors.patch b/debian/patches/improve-cors.patch
new file mode 100644
index 000000000..e90865ee9
--- /dev/null
+++ b/debian/patches/improve-cors.patch
@@ -0,0 +1,86 @@
+Description: improve CORS checks
+Author: Maxime Besson <maxime.besson at worteks.com>
+Origin: upstream, https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/merge_requests/767
+Bug: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3430
+Forwarded: not-needed
+Applied-Upstream: 2.16.6, commit:a34389a6
+Reviewed-By: Xavier Guimard <yadd at debian.org>
+Last-Update: 2025-07-12
+
+--- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm
++++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm
+@@ -1249,9 +1249,7 @@
+     # If this is a cross-domain request from the portal itself
+     # (Ajax SSL to a different VHost)
+     # we allow CORS
+-    if ( $req->origin
+-        and index( $self->conf->{portal}, $req->origin ) == 0 )
+-    {
++    if ( $self->_checkSelfCors($req) ) {
+         $self->logger->debug('AJAX request from portal, allowing CORS');
+         push @{ $res->[1] },
+           "Access-Control-Allow-Origin"      => $req->origin,
+@@ -1265,6 +1263,21 @@
+     return $res;
+ }
+ 
++sub _checkSelfCors {
++    my ( $self, $req ) = @_;
++
++    if ( $req->origin ) {
++        my $origin = URI->new( $req->origin );
++        my $portal = URI->new( $self->conf->{portal} );
++
++        return (  $origin->scheme
++              and $portal->scheme eq $origin->scheme
++              and $origin->host_port
++              and $origin->host_port eq $portal->host_port );
++    }
++    return;
++}
++
+ sub sendRawHtml {
+     my ($self) = $_[0];
+     my $res = Lemonldap::NG::Common::PSGI::sendRawHtml(@_);
+--- a/lemonldap-ng-portal/t/01-CSP-and-CORS-headers.t
++++ b/lemonldap-ng-portal/t/01-CSP-and-CORS-headers.t
+@@ -23,6 +23,14 @@
+     }
+ );
+ 
++# Test request from alternate vhost to portal
++checkCorsAllowed( $client, "http://auth.example.com",    1 );
++checkCorsAllowed( $client, "http://auth.example.com:80", 1 );
++checkCorsAllowed( $client, "http://auth.example.comm",   0 );
++checkCorsAllowed( $client, "http://auth.example.co",     0 );
++checkCorsAllowed( $client, "http://example.com",         0 );
++checkCorsAllowed( $client, "https://auth.example.com",   0 );
++
+ # Test normal first access
+ # ------------------------
+ ok( $res = $client->_get('/'), 'Unauth JSON request' );
+@@ -157,6 +165,24 @@
+ 
+ done_testing( count() );
+ 
++sub checkCorsAllowed {
++    my ( $client, $origin, $result ) = @_;
++    ok(
++        my $res = $client->_get( '/', custom => { HTTP_ORIGIN => "$origin" } ),
++        "Unauth JSON request from $origin"
++    );
++    my %headers = @{ $res->[1] };
++    if ($result) {
++        is( $headers{'Access-Control-Allow-Origin'},
++            $origin, "$origin is allowed" );
++    }
++    else {
++        ok( !$headers{'Access-Control-Allow-Origin'},
++            "$origin is not allowed" );
++    }
++    count(2);
++}
++
+ sub checkCorsPolicy {
+     my ($res) = @_;
+     my %headers = @{ $res->[1] };
diff --git a/debian/patches/series b/debian/patches/series
index bbd446de9..dbe6dbcf9 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -16,3 +16,8 @@ fix-xss-in-upgrade-plugin.patch
 CVE-2024-52948.patch
 fix-test-when-ldap-server-exists.patch
 CVE-2025-31510.patch
+fix-bad-table-name.patch
+fix-oidc-fixed-server-in-case-of-error.patch
+fix-kerberos-js.patch
+improve-cors.patch
+fix-path-info.patch


More information about the pkg-perl-maintainers mailing list