core_ACL: Add ACL library.
git-svn-id: http://simplesamlphp.googlecode.com/svn/trunk@1633 44740490-163a-0410-bde0-09ae8108e29a
This commit is contained in:
parent
3e6c51efcf
commit
be2cf89c8c
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file defines "named" access control lists, which can
|
||||
* be reused in several places.
|
||||
*/
|
||||
$config = array(
|
||||
|
||||
'adminlist' => array(
|
||||
//array('allow', 'equals', 'mail', 'admin1@example.org'),
|
||||
//array('allow', 'has', 'groups', 'admin'),
|
||||
/* The default action is to deny access. */
|
||||
),
|
||||
|
||||
'example-simple' => array(
|
||||
array('allow', 'equals', 'mail', 'admin1@example.org'),
|
||||
array('allow', 'equals', 'mail', 'admin2@example.org'),
|
||||
/* The default action is to deny access. */
|
||||
),
|
||||
|
||||
'example-deny-some' => array(
|
||||
array('deny', 'equals', 'mail', 'eviluser@example.org'),
|
||||
array('allow'), /* Allow everybody else. */
|
||||
),
|
||||
|
||||
'example-maildomain' => array(
|
||||
array('allow', 'equals-preg', 'mail', '/@example\.org$/'),
|
||||
/* The default action is to deny access. */
|
||||
),
|
||||
|
||||
'example-allow-employees' => array(
|
||||
array('allow', 'has', 'eduPersonAffiliation', 'employee'),
|
||||
/* The default action is to deny access. */
|
||||
),
|
||||
|
||||
'example-allow-employees-not-students' => array(
|
||||
array('deny', 'has', 'eduPersonAffiliation', 'student'),
|
||||
array('allow', 'has', 'eduPersonAffiliation', 'employee'),
|
||||
/* The default action is to deny access. */
|
||||
),
|
||||
|
||||
'example-deny-student-except-one' => array(
|
||||
array('deny', 'and',
|
||||
array('has', 'eduPersonAffiliation', 'student'),
|
||||
array('not', 'equals', 'mail', 'user@example.org'),
|
||||
),
|
||||
array('allow'),
|
||||
),
|
||||
|
||||
'example-allow-or' => array(
|
||||
array('allow', 'or',
|
||||
array('equals', 'eduPersonAffiliation', 'student', 'member'),
|
||||
array('equals', 'mail', 'someuser@example2.org'),
|
||||
),
|
||||
),
|
||||
|
||||
'example-allow-all' => array(
|
||||
array('allow'),
|
||||
),
|
||||
|
||||
);
|
|
@ -0,0 +1,307 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Generic library for access control lists.
|
||||
*
|
||||
* @package simpleSAMLphp
|
||||
* @version $Id$
|
||||
*/
|
||||
class sspmod_core_ACL {
|
||||
|
||||
/**
|
||||
* The access control list, as an array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $acl;
|
||||
|
||||
|
||||
/**
|
||||
* Initializer for this access control list.
|
||||
*
|
||||
* @param array|string $acl The access control list.
|
||||
*/
|
||||
public function __construct($acl) {
|
||||
assert('is_string($acl) || is_array($acl)');
|
||||
|
||||
if (is_string($acl)) {
|
||||
$acl = self::getById($acl);
|
||||
}
|
||||
|
||||
foreach ($acl as $rule) {
|
||||
if (!is_array($rule)) {
|
||||
throw new SimpleSAML_Error_Exception('Invalid rule in access control list: ' . var_export($rule, TRUE));
|
||||
}
|
||||
if (count($rule) === 0) {
|
||||
throw new SimpleSAML_Error_Exception('Empty rule in access control list.');
|
||||
}
|
||||
|
||||
$action = array_shift($rule);
|
||||
if ($action !== 'allow' && $action !== 'deny') {
|
||||
throw new SimpleSAML_Error_Exception('Invalid action in rule in access control list: ' . var_export($action, TRUE));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->acl = $acl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve an access control list with the given id.
|
||||
*
|
||||
* @param string $id The id of the access control list.
|
||||
* @return array The access control list array.
|
||||
*/
|
||||
private static function getById($id) {
|
||||
assert('is_string($id)');
|
||||
|
||||
$config = SimpleSAML_Configuration::getConfig('acl.php');
|
||||
if (!$config->hasValue($id)) {
|
||||
throw new SimpleSAML_Error_Exception('No ACL with id ' . var_export($id, TRUE) . ' in config/acl.php.');
|
||||
}
|
||||
|
||||
return $config->getArray($id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Match the attributes against the access control list.
|
||||
*
|
||||
* @param array $attributes The attributes of an user.
|
||||
* @return boolean TRUE if the user is allowed to access the resource, FALSE if not.
|
||||
*/
|
||||
public function allows(array $attributes) {
|
||||
|
||||
foreach ($this->acl as $rule) {
|
||||
$action = array_shift($rule);
|
||||
|
||||
if (!self::match($attributes, $rule)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($action === 'allow') {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Match the attributes against the given rule.
|
||||
*
|
||||
* @param array $attributes The attributes of an user.
|
||||
* @param array $rule The rule we should check.
|
||||
* @return boolean TRUE if the rule matches, FALSE if not.
|
||||
*/
|
||||
private static function match(array $attributes, array $rule) {
|
||||
|
||||
$op = array_shift($rule);
|
||||
if ($op === NULL) {
|
||||
/* An empty rule always matches. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
switch($op) {
|
||||
case 'and':
|
||||
return self::opAnd($attributes, $rule);
|
||||
case 'equals':
|
||||
return self::opEquals($attributes, $rule);
|
||||
case 'equals-preg':
|
||||
return self::opEqualsPreg($attributes, $rule);
|
||||
case 'has':
|
||||
return self::opHas($attributes, $rule);
|
||||
case 'has-preg':
|
||||
return self::opHasPreg($attributes, $rule);
|
||||
case 'not':
|
||||
return !self::match($attributes, $rule);
|
||||
case 'or':
|
||||
return self::opOr($attributes, $rule);
|
||||
default:
|
||||
throw new SimpleSAML_Error_Exception('Invalid ACL operation: ' . var_export($op. TRUE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 'and' match operator.
|
||||
*
|
||||
* @param array $attributes The attributes of an user.
|
||||
* @param array $rule The rule we should check.
|
||||
* @return boolean TRUE if the rule matches, FALSE if not.
|
||||
*/
|
||||
private static function opAnd($attributes, $rule) {
|
||||
|
||||
foreach ($rule as $subRule) {
|
||||
if (!self::match($attributes, $subRule)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* All matches. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 'equals' match operator.
|
||||
*
|
||||
* @param array $attributes The attributes of an user.
|
||||
* @param array $rule The rule we should check.
|
||||
* @return boolean TRUE if the rule matches, FALSE if not.
|
||||
*/
|
||||
private static function opEquals($attributes, $rule) {
|
||||
|
||||
$attributeName = array_shift($rule);
|
||||
|
||||
if (!array_key_exists($attributeName, $attributes)) {
|
||||
$attributeValues = array();
|
||||
} else {
|
||||
$attributeValues = $attributes[$attributeName];
|
||||
}
|
||||
|
||||
foreach ($rule as $value) {
|
||||
$found = FALSE;
|
||||
foreach ($attributeValues as $i => $v) {
|
||||
if ($value !== $v) {
|
||||
continue;
|
||||
}
|
||||
unset($attributeValues[$i]);
|
||||
$found = TRUE;
|
||||
break;
|
||||
}
|
||||
if (!$found) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (!empty($attributeValues)) {
|
||||
/* One of the attribute values didn't match. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* All the values in the attribute matched one in the rule. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 'equals-preg' match operator.
|
||||
*
|
||||
* @param array $attributes The attributes of an user.
|
||||
* @param array $rule The rule we should check.
|
||||
* @return boolean TRUE if the rule matches, FALSE if not.
|
||||
*/
|
||||
private static function opEqualsPreg($attributes, $rule) {
|
||||
|
||||
$attributeName = array_shift($rule);
|
||||
|
||||
if (!array_key_exists($attributeName, $attributes)) {
|
||||
$attributeValues = array();
|
||||
} else {
|
||||
$attributeValues = $attributes[$attributeName];
|
||||
}
|
||||
|
||||
foreach ($rule as $pattern) {
|
||||
$found = FALSE;
|
||||
foreach ($attributeValues as $i => $v) {
|
||||
if (!preg_match($pattern, $v)) {
|
||||
continue;
|
||||
}
|
||||
unset($attributeValues[$i]);
|
||||
$found = TRUE;
|
||||
break;
|
||||
}
|
||||
if (!$found) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($attributeValues)) {
|
||||
/* One of the attribute values didn't match. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* All the values in the attribute matched one in the rule. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 'has' match operator.
|
||||
*
|
||||
* @param array $attributes The attributes of an user.
|
||||
* @param array $rule The rule we should check.
|
||||
* @return boolean TRUE if the rule matches, FALSE if not.
|
||||
*/
|
||||
private static function opHas($attributes, $rule) {
|
||||
|
||||
$attributeName = array_shift($rule);
|
||||
|
||||
if (!array_key_exists($attributeName, $attributes)) {
|
||||
$attributeValues = array();
|
||||
} else {
|
||||
$attributeValues = $attributes[$attributeName];
|
||||
}
|
||||
|
||||
foreach ($rule as $value) {
|
||||
if (!in_array($value, $attributeValues, TRUE)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Found all values in the rule in the attribute. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 'has-preg' match operator.
|
||||
*
|
||||
* @param array $attributes The attributes of an user.
|
||||
* @param array $rule The rule we should check.
|
||||
* @return boolean TRUE if the rule matches, FALSE if not.
|
||||
*/
|
||||
private static function opHasPreg($attributes, $rule) {
|
||||
|
||||
$attributeName = array_shift($rule);
|
||||
|
||||
if (!array_key_exists($attributeName, $attributes)) {
|
||||
$attributeValues = array();
|
||||
} else {
|
||||
$attributeValues = $attributes[$attributeName];
|
||||
}
|
||||
|
||||
foreach ($rule as $pattern) {
|
||||
$matches = preg_grep($pattern, $attributeValues);
|
||||
if (count($matches) === 0) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Found all values in the rule in the attribute. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 'or' match operator.
|
||||
*
|
||||
* @param array $attributes The attributes of an user.
|
||||
* @param array $rule The rule we should check.
|
||||
* @return boolean TRUE if the rule matches, FALSE if not.
|
||||
*/
|
||||
private static function opOr($attributes, $rule) {
|
||||
|
||||
foreach ($rule as $subRule) {
|
||||
if (self::match($attributes, $subRule)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* None matches. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue