Files
librenms-librenms/LibreNMS/Authentication/RadiusAuthorizer.php
Tony Murray b51ae39e71 Radius enforce roles (#15294)
Add new setting to specify if user roles will be set at login or not.
Without this setting enabled, roles are only set when the user is first created and never after that. If roles set via Filter-ID attribute or radius.default_roles change, they will never be reflected on existing users.
For that reason, the default is set to enabled.  Historically, radius did not enforce roles.
2023-09-07 11:28:35 -05:00

76 lines
2.5 KiB
PHP

<?php
namespace LibreNMS\Authentication;
use App\Models\User;
use Dapphp\Radius\Radius;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use LibreNMS\Config;
use LibreNMS\Enum\LegacyAuthLevel;
use LibreNMS\Exceptions\AuthenticationException;
use LibreNMS\Util\Debug;
class RadiusAuthorizer extends MysqlAuthorizer
{
protected static $HAS_AUTH_USERMANAGEMENT = true;
protected static $CAN_UPDATE_USER = true;
protected static $CAN_UPDATE_PASSWORDS = false;
protected Radius $radius;
private array $roles = []; // temp cache of roles
public function __construct()
{
$this->radius = new Radius(Config::get('radius.hostname'), Config::get('radius.secret'), Config::get('radius.suffix'), Config::get('radius.timeout'), Config::get('radius.port'));
}
public function authenticate($credentials)
{
if (empty($credentials['username'])) {
throw new AuthenticationException('Username is required');
}
if (Debug::isEnabled()) {
$this->radius->setDebug(true);
}
$password = $credentials['password'] ?? null;
if ($this->radius->accessRequest($credentials['username'], $password) === true) {
$user = User::thisAuth()->firstOrNew(['username' => $credentials['username']], [
'auth_type' => LegacyAuth::getType(),
'can_modify_passwd' => 0,
]);
$new_user = ! $user->exists;
$user->save();
// cache a single role from the Filter-ID attribute now because attributes are cleared every accessRequest
$filter_id_attribute = $this->radius->getAttribute(11);
if ($filter_id_attribute && Str::startsWith($filter_id_attribute, 'librenms_role_')) {
$this->roles[$credentials['username']] = [substr($filter_id_attribute, 14)];
}
if (Config::get('radius.enforce_roles') || $new_user) {
$user->setRoles($this->roles[$credentials['username']] ?? $this->getDefaultRoles(), true);
}
return true;
}
throw new AuthenticationException();
}
public function getRoles(string $username): array|false
{
return $this->roles[$username] ?? false;
}
private function getDefaultRoles(): array
{
// return roles or translate from the old radius.default_level
return Config::get('radius.default_roles')
?: Arr::wrap(LegacyAuthLevel::from(Config::get('radius.default_level') ?? 1)->getName());
}
}