2016-03-24 15:29:39 +01:00
|
|
|
<?php
|
|
|
|
/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
|
|
|
|
|
|
|
|
namespace Icinga\Authentication;
|
|
|
|
|
|
|
|
class Role
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Name of the role
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $name;
|
|
|
|
|
2021-02-01 15:04:36 +01:00
|
|
|
/**
|
|
|
|
* The role from which to inherit privileges
|
|
|
|
*
|
|
|
|
* @var Role
|
|
|
|
*/
|
|
|
|
protected $parent;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The roles to which privileges are inherited
|
|
|
|
*
|
|
|
|
* @var Role[]
|
|
|
|
*/
|
|
|
|
protected $children;
|
|
|
|
|
2021-02-02 13:20:29 +01:00
|
|
|
/**
|
|
|
|
* Whether restrictions should not apply to owners of the role
|
|
|
|
*
|
|
|
|
* @var bool
|
|
|
|
*/
|
|
|
|
protected $unrestricted = false;
|
|
|
|
|
2016-03-24 15:29:39 +01:00
|
|
|
/**
|
|
|
|
* Permissions of the role
|
|
|
|
*
|
|
|
|
* @var string[]
|
|
|
|
*/
|
2021-01-29 15:48:48 +01:00
|
|
|
protected $permissions = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Refusals of the role
|
|
|
|
*
|
|
|
|
* @var string[]
|
|
|
|
*/
|
|
|
|
protected $refusals = [];
|
2016-03-24 15:29:39 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Restrictions of the role
|
|
|
|
*
|
|
|
|
* @var string[]
|
|
|
|
*/
|
2021-01-29 15:48:48 +01:00
|
|
|
protected $restrictions = [];
|
2016-03-24 15:29:39 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the name of the role
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getName()
|
|
|
|
{
|
|
|
|
return $this->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the name of the role
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setName($name)
|
|
|
|
{
|
|
|
|
$this->name = $name;
|
2021-01-29 15:48:48 +01:00
|
|
|
|
2016-03-24 15:29:39 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2021-02-01 15:04:36 +01:00
|
|
|
/**
|
|
|
|
* Get the role from which privileges are inherited
|
|
|
|
*
|
|
|
|
* @return Role
|
|
|
|
*/
|
|
|
|
public function getParent()
|
|
|
|
{
|
|
|
|
return $this->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the role from which to inherit privileges
|
|
|
|
*
|
|
|
|
* @param Role $parent
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setParent(Role $parent)
|
|
|
|
{
|
|
|
|
$this->parent = $parent;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the roles to which privileges are inherited
|
|
|
|
*
|
|
|
|
* @return Role[]
|
|
|
|
*/
|
|
|
|
public function getChildren()
|
|
|
|
{
|
|
|
|
return $this->children;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the roles to which inherit privileges
|
|
|
|
*
|
|
|
|
* @param Role[] $children
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setChildren(array $children)
|
|
|
|
{
|
|
|
|
$this->children = $children;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a role to which inherit privileges
|
|
|
|
*
|
|
|
|
* @param Role $role
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function addChild(Role $role)
|
|
|
|
{
|
|
|
|
$this->children[] = $role;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2021-02-02 13:20:29 +01:00
|
|
|
/**
|
|
|
|
* Get whether restrictions should not apply to owners of the role
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function isUnrestricted()
|
|
|
|
{
|
|
|
|
return $this->unrestricted;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set whether restrictions should not apply to owners of the role
|
|
|
|
*
|
|
|
|
* @param bool $state
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setIsUnrestricted($state)
|
|
|
|
{
|
|
|
|
$this->unrestricted = (bool) $state;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2016-03-24 16:11:31 +01:00
|
|
|
/**
|
2016-03-29 11:19:03 +02:00
|
|
|
* Get the permissions of the role
|
2016-03-24 16:11:31 +01:00
|
|
|
*
|
2016-03-29 11:19:03 +02:00
|
|
|
* @return string[]
|
2016-03-24 16:11:31 +01:00
|
|
|
*/
|
2016-03-29 11:19:03 +02:00
|
|
|
public function getPermissions()
|
2016-03-24 16:11:31 +01:00
|
|
|
{
|
2016-03-29 11:19:03 +02:00
|
|
|
return $this->permissions;
|
2016-03-24 16:11:31 +01:00
|
|
|
}
|
|
|
|
|
2016-03-24 15:29:39 +01:00
|
|
|
/**
|
2016-03-29 11:19:03 +02:00
|
|
|
* Set the permissions of the role
|
2016-03-24 15:29:39 +01:00
|
|
|
*
|
2016-03-29 11:19:03 +02:00
|
|
|
* @param string[] $permissions
|
|
|
|
*
|
|
|
|
* @return $this
|
2016-03-24 15:29:39 +01:00
|
|
|
*/
|
2016-03-29 11:19:03 +02:00
|
|
|
public function setPermissions(array $permissions)
|
2016-03-24 15:29:39 +01:00
|
|
|
{
|
2016-03-29 11:19:03 +02:00
|
|
|
$this->permissions = $permissions;
|
2021-01-29 15:48:48 +01:00
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the refusals of the role
|
|
|
|
*
|
|
|
|
* @return string[]
|
|
|
|
*/
|
|
|
|
public function getRefusals()
|
|
|
|
{
|
|
|
|
return $this->refusals;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the refusals of the role
|
|
|
|
*
|
|
|
|
* @param array $refusals
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setRefusals(array $refusals)
|
|
|
|
{
|
|
|
|
$this->refusals = $refusals;
|
|
|
|
|
2016-03-29 11:19:03 +02:00
|
|
|
return $this;
|
2016-03-24 15:29:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the restrictions of the role
|
|
|
|
*
|
|
|
|
* @param string $name Optional name of the restriction
|
|
|
|
*
|
|
|
|
* @return string[]|null
|
|
|
|
*/
|
|
|
|
public function getRestrictions($name = null)
|
|
|
|
{
|
|
|
|
$restrictions = $this->restrictions;
|
|
|
|
|
|
|
|
if ($name === null) {
|
|
|
|
return $restrictions;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($restrictions[$name])) {
|
|
|
|
return $restrictions[$name];
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
2016-03-29 11:19:03 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the restrictions of the role
|
|
|
|
*
|
|
|
|
* @param string[] $restrictions
|
|
|
|
*
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setRestrictions(array $restrictions)
|
|
|
|
{
|
|
|
|
$this->restrictions = $restrictions;
|
2021-01-29 15:48:48 +01:00
|
|
|
|
2016-03-29 11:19:03 +02:00
|
|
|
return $this;
|
|
|
|
}
|
2021-01-22 15:47:36 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether this role grants the given permission
|
|
|
|
*
|
|
|
|
* @param string $permission
|
2021-02-01 15:04:36 +01:00
|
|
|
* @param bool $ignoreParent Only evaluate the role's own permissions
|
2021-03-24 09:10:06 +01:00
|
|
|
* @param bool $cascadeUpwards `false` if `foo/bar/*` and `foo/bar/raboof` should not match `foo/*`
|
2021-01-22 15:47:36 +01:00
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
2021-03-24 09:10:06 +01:00
|
|
|
public function grants($permission, $ignoreParent = false, $cascadeUpwards = true)
|
2021-01-22 15:47:36 +01:00
|
|
|
{
|
|
|
|
foreach ($this->permissions as $grantedPermission) {
|
2021-03-24 09:10:06 +01:00
|
|
|
if ($this->match($grantedPermission, $permission, $cascadeUpwards)) {
|
2021-01-29 15:48:48 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 15:04:36 +01:00
|
|
|
if (! $ignoreParent && $this->getParent() !== null) {
|
2021-03-24 09:10:06 +01:00
|
|
|
return $this->getParent()->grants($permission, false, $cascadeUpwards);
|
2021-02-01 15:04:36 +01:00
|
|
|
}
|
|
|
|
|
2021-01-29 15:48:48 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether this role denies the given permission
|
|
|
|
*
|
|
|
|
* @param string $permission
|
2021-02-01 15:04:36 +01:00
|
|
|
* @param bool $ignoreParent Only evaluate the role's own refusals
|
2021-01-29 15:48:48 +01:00
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
2021-02-01 15:04:36 +01:00
|
|
|
public function denies($permission, $ignoreParent = false)
|
2021-01-29 15:48:48 +01:00
|
|
|
{
|
|
|
|
foreach ($this->refusals as $refusedPermission) {
|
|
|
|
if ($this->match($refusedPermission, $permission, false)) {
|
2021-01-22 15:47:36 +01:00
|
|
|
return true;
|
|
|
|
}
|
2021-01-29 15:48:48 +01:00
|
|
|
}
|
2021-01-22 15:47:36 +01:00
|
|
|
|
2021-02-01 15:04:36 +01:00
|
|
|
if (! $ignoreParent && $this->getParent() !== null) {
|
|
|
|
return $this->getParent()->denies($permission);
|
|
|
|
}
|
|
|
|
|
2021-01-29 15:48:48 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get whether the role expression matches the required permission
|
|
|
|
*
|
|
|
|
* @param string $roleExpression
|
|
|
|
* @param string $requiredPermission
|
|
|
|
* @param bool $cascadeUpwards `false` if `foo/bar/*` and `foo/bar/raboof` should not match `foo/*`
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
protected function match($roleExpression, $requiredPermission, $cascadeUpwards = true)
|
|
|
|
{
|
|
|
|
if ($roleExpression === '*' || $roleExpression === $requiredPermission) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$requiredWildcard = strpos($requiredPermission, '*');
|
|
|
|
if ($requiredWildcard !== false) {
|
|
|
|
if (($grantedWildcard = strpos($roleExpression, '*')) !== false) {
|
|
|
|
$wildcard = $cascadeUpwards ? min($requiredWildcard, $grantedWildcard) : $grantedWildcard;
|
2021-01-22 15:47:36 +01:00
|
|
|
} else {
|
2021-01-29 15:48:48 +01:00
|
|
|
$wildcard = $cascadeUpwards ? $requiredWildcard : false;
|
2021-01-22 15:47:36 +01:00
|
|
|
}
|
2021-01-29 15:48:48 +01:00
|
|
|
} else {
|
|
|
|
$wildcard = strpos($roleExpression, '*');
|
|
|
|
}
|
2021-01-22 15:47:36 +01:00
|
|
|
|
2021-01-29 15:48:48 +01:00
|
|
|
if ($wildcard !== false && $wildcard > 0) {
|
|
|
|
if (substr($requiredPermission, 0, $wildcard) === substr($roleExpression, 0, $wildcard)) {
|
2021-01-22 15:47:36 +01:00
|
|
|
return true;
|
|
|
|
}
|
2021-01-29 15:48:48 +01:00
|
|
|
} elseif ($requiredPermission === $roleExpression) {
|
|
|
|
return true;
|
2021-01-22 15:47:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-24 15:29:39 +01:00
|
|
|
}
|