2017-11-18 11:33:03 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace LibreNMS\Authentication;
|
|
|
|
|
2023-08-28 00:13:40 -05:00
|
|
|
use App\Models\User;
|
2017-11-18 11:33:03 +01:00
|
|
|
use Dapphp\Radius\Radius;
|
2023-08-28 00:13:40 -05:00
|
|
|
use Illuminate\Support\Arr;
|
|
|
|
use Illuminate\Support\Str;
|
2017-11-18 11:33:03 +01:00
|
|
|
use LibreNMS\Config;
|
2023-08-28 00:13:40 -05:00
|
|
|
use LibreNMS\Enum\LegacyAuthLevel;
|
2017-11-18 11:33:03 +01:00
|
|
|
use LibreNMS\Exceptions\AuthenticationException;
|
2021-04-29 22:42:18 -05:00
|
|
|
use LibreNMS\Util\Debug;
|
2017-11-18 11:33:03 +01:00
|
|
|
|
2018-02-06 15:20:34 -06:00
|
|
|
class RadiusAuthorizer extends MysqlAuthorizer
|
2017-11-18 11:33:03 +01:00
|
|
|
{
|
2021-04-01 17:35:18 +02:00
|
|
|
protected static $HAS_AUTH_USERMANAGEMENT = true;
|
|
|
|
protected static $CAN_UPDATE_USER = true;
|
|
|
|
protected static $CAN_UPDATE_PASSWORDS = false;
|
2017-11-18 11:33:03 +01:00
|
|
|
|
2023-08-28 00:13:40 -05:00
|
|
|
protected Radius $radius;
|
|
|
|
|
|
|
|
private array $roles = []; // temp cache of roles
|
2017-11-18 11:33:03 +01:00
|
|
|
|
|
|
|
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'));
|
|
|
|
}
|
|
|
|
|
2019-03-05 00:24:14 -06:00
|
|
|
public function authenticate($credentials)
|
2017-11-18 11:33:03 +01:00
|
|
|
{
|
2019-03-05 00:24:14 -06:00
|
|
|
if (empty($credentials['username'])) {
|
2017-11-18 11:33:03 +01:00
|
|
|
throw new AuthenticationException('Username is required');
|
|
|
|
}
|
|
|
|
|
2021-04-29 22:42:18 -05:00
|
|
|
if (Debug::isEnabled()) {
|
2017-11-18 11:33:03 +01:00
|
|
|
$this->radius->setDebug(true);
|
|
|
|
}
|
|
|
|
|
2019-03-05 00:24:14 -06:00
|
|
|
$password = $credentials['password'] ?? null;
|
|
|
|
if ($this->radius->accessRequest($credentials['username'], $password) === true) {
|
2023-08-28 00:13:40 -05:00
|
|
|
$user = User::thisAuth()->firstOrNew(['username' => $credentials['username']], [
|
|
|
|
'auth_type' => LegacyAuth::getType(),
|
|
|
|
'can_modify_passwd' => 0,
|
|
|
|
]);
|
2023-09-07 11:28:35 -05:00
|
|
|
$new_user = ! $user->exists;
|
2023-08-28 00:13:40 -05:00
|
|
|
$user->save();
|
|
|
|
|
|
|
|
// cache a single role from the Filter-ID attribute now because attributes are cleared every accessRequest
|
2022-11-09 17:10:33 +01:00
|
|
|
$filter_id_attribute = $this->radius->getAttribute(11);
|
2023-08-28 00:13:40 -05:00
|
|
|
if ($filter_id_attribute && Str::startsWith($filter_id_attribute, 'librenms_role_')) {
|
|
|
|
$this->roles[$credentials['username']] = [substr($filter_id_attribute, 14)];
|
2022-11-09 17:10:33 +01:00
|
|
|
}
|
|
|
|
|
2023-09-07 11:28:35 -05:00
|
|
|
if (Config::get('radius.enforce_roles') || $new_user) {
|
|
|
|
$user->setRoles($this->roles[$credentials['username']] ?? $this->getDefaultRoles(), true);
|
|
|
|
}
|
2023-08-28 23:38:09 -05:00
|
|
|
|
2017-11-18 11:33:03 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new AuthenticationException();
|
|
|
|
}
|
2023-08-28 00:13:40 -05:00
|
|
|
|
2023-08-28 23:38:09 -05:00
|
|
|
public function getRoles(string $username): array|false
|
2023-08-28 00:13:40 -05:00
|
|
|
{
|
2023-08-28 23:38:09 -05:00
|
|
|
return $this->roles[$username] ?? false;
|
2023-08-28 00:13:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
2017-11-18 11:33:03 +01:00
|
|
|
}
|