From 8d8c40db0e5eda0e9c93f555c53bcceffda94fb1 Mon Sep 17 00:00:00 2001 From: Rene Krenn Date: Tue, 14 Jul 2026 15:57:40 +0200 Subject: [PATCH] MT#65464 Fix LDAP OTP registration crash on /api/otpsecret LDAP login stored a raw DB::admins row as $c->user, so API response logging failed when fetching the OTP QR after an invalid OTP on login_jwt. Wrap the admin in RoleFromRealm, pass the admin auth realm to set_authenticated, logout on OTP failure, and make Message logging tolerate raw user rows or role lookup failures. Change-Id: I29fda2324eadc7fb1f25f06ae6418ab594b69fa0 (cherry picked from commit 70d5c894a62563a621868d01193ca5a1302f9bee) --- lib/NGCP/Panel/Utils/Auth.pm | 27 ++++++++++++++++++++++++++- lib/NGCP/Panel/Utils/Message.pm | 15 +++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/NGCP/Panel/Utils/Auth.pm b/lib/NGCP/Panel/Utils/Auth.pm index 9f9fc0225f..dd54754bdf 100644 --- a/lib/NGCP/Panel/Utils/Auth.pm +++ b/lib/NGCP/Panel/Utils/Auth.pm @@ -170,7 +170,9 @@ sub perform_auth { $log_failed_login_attempt = 0; # do not log failed attempt if there was an ldap error } else { $res = 1; - $c->set_authenticated($dbadmin); # logs the user in and calls persist_user + my $auth_user = wrap_admin_auth_user($c, $dbadmin, $bcrypt_realm); + $c->set_authenticated($auth_user, $bcrypt_realm); + $auth_user->auth_realm($bcrypt_realm) if $auth_user->can('auth_realm'); } } else { $c->log->error("unsupported auth_mode " . $dbadmin->auth_mode); @@ -187,6 +189,7 @@ sub perform_auth { }) if ($dbadmin->show_otp_registration_info); } else { $res = -3; + $c->user->logout if $c->user_exists; } } @@ -324,6 +327,7 @@ sub perform_subscriber_auth { if NGCP::Panel::Utils::Auth::get_subscriber_show_otp_registration_info($c,$sub); } else { $res = -3; + $c->user->logout if $c->user_exists; } } @@ -913,6 +917,27 @@ sub get_subscriber_otp_secret { } +sub wrap_admin_auth_user { + my ($c, $dbadmin, $realm) = @_; + return $dbadmin unless $dbadmin; + + my $store = eval { $c->get_auth_realm($realm)->store }; + unless ($store) { + $c->log->error("wrap_admin_auth_user: unknown auth realm '$realm'"); + return $dbadmin; + } + + my $auth_user = $store->find_user({ id => $dbadmin->id }, $c) + // $store->find_user({ login => $dbadmin->login }, $c); + if ($auth_user && $auth_user->can('auth_realm')) { + $auth_user->auth_realm($realm); + return $auth_user; + } + + $c->log->error("wrap_admin_auth_user: failed to wrap admin id=" . $dbadmin->id); + return $dbadmin; +} + sub clear_otp_secret { my ($c,$user) = @_; diff --git a/lib/NGCP/Panel/Utils/Message.pm b/lib/NGCP/Panel/Utils/Message.pm index 7a47443e1a..1b9f13494c 100644 --- a/lib/NGCP/Panel/Utils/Message.pm +++ b/lib/NGCP/Panel/Utils/Message.pm @@ -52,9 +52,20 @@ sub get_log_params { my $r_user = ''; my $is_subscriber = 0; if ($c->user_exists) { - if ($c->user->roles eq 'admin' || $c->user->roles eq 'reseller') { + my $roles; + if ($c->user->can('roles')) { + local $@; + $roles = eval { $c->user->roles }; + undef $roles if $@; + } + if (defined $roles && ($roles eq 'admin' || $roles eq 'reseller')) { + $r_user = $c->user->login; + } elsif (defined $roles && ($roles eq 'subscriberadmin' || $roles eq 'subscriber')) { + $r_user = $c->qs($c->user->webusername . '@' . $c->user->domain->domain); + $is_subscriber = 1; + } elsif (ref($c->user) eq 'NGCP::Panel::Model::DB::admins') { $r_user = $c->user->login; - } elsif ($c->user->roles eq 'subscriberadmin' || $c->user->roles eq 'subscriber') { + } elsif (ref($c->user) eq 'NGCP::Panel::Model::DB::provisioning_voip_subscribers') { $r_user = $c->qs($c->user->webusername . '@' . $c->user->domain->domain); $is_subscriber = 1; }