Package: release.debian.org Severity: normal Tags: bookworm X-Debbugs-Cc: [email protected], [email protected] Control: affects -1 + src:lemonldap-ng User: [email protected] 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
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 <[email protected]> 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 <[email protected]> +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 <[email protected]> +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 <[email protected]> +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 <[email protected]> +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 <[email protected]> +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 <[email protected]> +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 <[email protected]> +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 <[email protected]> +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

