commit
590262ebb4
|
@ -1,83 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Authentication;
|
||||
|
||||
use Icinga\Exception;
|
||||
use Zend_Session_Namespace as SessionNamespace;
|
||||
|
||||
class Auth
|
||||
{
|
||||
protected static $instance;
|
||||
protected $userInfo;
|
||||
protected $session;
|
||||
|
||||
final private function __construct()
|
||||
{
|
||||
$this->session = new SessionNamespace('IcingaAuth');
|
||||
}
|
||||
|
||||
public static function getInstance()
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new Auth();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function isAuthenticated()
|
||||
{
|
||||
if ($this->userInfo === null) {
|
||||
if ($sessionInfo = $this->session->userInfo) {
|
||||
$this->userInfo = $sessionInfo;
|
||||
}
|
||||
}
|
||||
return is_object($this->userInfo) && ! empty($this->userInfo->username);
|
||||
}
|
||||
|
||||
public function getUsername()
|
||||
{
|
||||
$this->assertIsAuthenticated();
|
||||
return $this->userInfo->username;
|
||||
}
|
||||
|
||||
public function getEmail()
|
||||
{
|
||||
$this->assertIsAuthenticated();
|
||||
return $this->userInfo->email;
|
||||
}
|
||||
|
||||
public function setAuthenticatedUser(User $user)
|
||||
{
|
||||
$this->userInfo = (object) array(
|
||||
'username' => $user->username,
|
||||
'permissions' => $user->getPermissionList(),
|
||||
'email' => $user->email,
|
||||
);
|
||||
$this->session->userInfo = $this->userInfo;
|
||||
}
|
||||
|
||||
public function forgetAuthentication()
|
||||
{
|
||||
unset($this->session->userInfo);
|
||||
$this->userInfo = null;
|
||||
}
|
||||
|
||||
public function hasPermission($route, $flags = 0x01)
|
||||
{
|
||||
$this->assertBeingAuthenticated();
|
||||
if (! array_key_exists($route, $this->userInfo->permissions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->userInfo->permissions[$route] & $flags === $flags;
|
||||
}
|
||||
|
||||
protected function assertIsAuthenticated()
|
||||
{
|
||||
if (! $this->isAuthenticated()) {
|
||||
throw new Exception\ProgrammingError(
|
||||
'Cannot fetch properties of a non-authenticated user'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Authentication;
|
||||
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Authentication;
|
||||
namespace Icinga\Authentication\Backend;
|
||||
|
||||
use Icinga\Authentication\User as User;
|
||||
use Icinga\Protocol\Ldap;
|
||||
|
||||
class LdapUserBackend extends UserBackend
|
||||
class LdapUserBackend implements UserBackend
|
||||
{
|
||||
protected $connection;
|
||||
|
||||
protected function init()
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->connection = new Ldap\Connection($this->config);
|
||||
$this->connection = new Ldap\Connection($config);
|
||||
}
|
||||
|
||||
public function hasUsername($username)
|
||||
{
|
||||
if (! $username) {
|
||||
if (!$username) {
|
||||
return false;
|
||||
}
|
||||
return $this->connection->fetchOne(
|
||||
|
@ -40,18 +43,15 @@ class LdapUserBackend extends UserBackend
|
|||
if (empty($username) || empty($password)) {
|
||||
return false;
|
||||
}
|
||||
if (! $this->connection->testCredentials(
|
||||
|
||||
if (!$this->connection->testCredentials(
|
||||
$this->connection->fetchDN($this->selectUsername($username)),
|
||||
$password
|
||||
)) {
|
||||
) ) {
|
||||
return false;
|
||||
}
|
||||
$user = User::create(
|
||||
$this,
|
||||
array(
|
||||
'username' => $username,
|
||||
)
|
||||
);
|
||||
$user = new User($username);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Authentication;
|
||||
|
||||
class Credentials
|
||||
{
|
||||
protected $username;
|
||||
protected $password;
|
||||
protected $domain;
|
||||
|
||||
|
||||
public function __construct($username = "", $password = null, $domain = null)
|
||||
{
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
$this->domain = $domain;
|
||||
}
|
||||
|
||||
public function getUsername()
|
||||
{
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function setUsername($username)
|
||||
{
|
||||
return $this->username = $username;
|
||||
}
|
||||
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function setPassword($password)
|
||||
{
|
||||
return $this->password = $password;
|
||||
}
|
||||
|
||||
public function getDomain()
|
||||
{
|
||||
return $this->domain;
|
||||
}
|
||||
|
||||
public function setDomain($domain)
|
||||
{
|
||||
return $this->domain = $domain;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Authentication;
|
||||
|
||||
use Icinga\Application\Logger as Logger;
|
||||
|
||||
class Manager
|
||||
{
|
||||
const BACKEND_TYPE_USER = "User";
|
||||
const BACKEND_TYPE_GROUP = "Group";
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
private $user = null;
|
||||
private $groups = array();
|
||||
private $userBackend = null;
|
||||
private $groupBackend = null;
|
||||
private $session = null;
|
||||
|
||||
private function __construct($config = null, array $options = array())
|
||||
{
|
||||
if ($config === null) {
|
||||
$config = Config::getInstance()->authentication;
|
||||
}
|
||||
|
||||
if (isset($options["userBackendClass"])) {
|
||||
$this->userBackend = $options["userBackendClass"];
|
||||
} elseif ($config->users !== null) {
|
||||
$this->userBackend = initBackend(BACKEND_TYPE_USER, $config->users);
|
||||
}
|
||||
|
||||
if (isset($options["groupBackendClass"])) {
|
||||
$this->groupBackend = $options["groupBackendClass"];
|
||||
} elseif ($config->groups != null) {
|
||||
$this->groupBackend = initBackend(BACKEND_TYPE_GROUP, $config->groups);
|
||||
}
|
||||
|
||||
if (!isset($options["sessionClass"])) {
|
||||
$this->session = new PhpSession($config->session);
|
||||
} else {
|
||||
$this->session = $options["sessionClass"];
|
||||
}
|
||||
if (isset($options["writeSession"]) && $options["writeSession"] === true) {
|
||||
$this->session->read(true);
|
||||
} else {
|
||||
$this->session->read();
|
||||
}
|
||||
}
|
||||
|
||||
public static function getInstance($config = null, array $options = array())
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new Manager($config, $options);
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function clearInstance()
|
||||
{
|
||||
self::$instance = null;
|
||||
}
|
||||
|
||||
private function initBackend($authenticationTarget, $authenticationSource)
|
||||
{
|
||||
$userbackend = ucwords(strtolower($authenticationSource->backend));
|
||||
$class = '\\Icinga\\Authentication\\Backend\\' . $backend . $authenticationTarget. 'Backend';
|
||||
return new $class($authenticationSource);
|
||||
}
|
||||
|
||||
public function authenticate(Credentials $credentials, $persist = true)
|
||||
{
|
||||
if (!$this->userBackend->hasUsername($credentials)) {
|
||||
Logger::info("Unknown user %s tried to log in", $credentials->getUsername());
|
||||
return false;
|
||||
}
|
||||
$this->user = $this->userBackend->authenticate($credentials);
|
||||
if ($this->user == null) {
|
||||
Logger::info("Invalid credentials for user %s provided", $credentials->getUsername());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($persist == true) {
|
||||
$this->persistCurrentUser();
|
||||
$this->session->write();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function persistCurrentUser()
|
||||
{
|
||||
$this->session->set("user", $this->user);
|
||||
}
|
||||
|
||||
public function authenticateFromSession()
|
||||
{
|
||||
$this->user = $this->session->get("user", null);
|
||||
}
|
||||
|
||||
public function isAuthenticated($ignoreSession = false)
|
||||
{
|
||||
if ($this->user === null && !$ignoreSession) {
|
||||
$this->authenticateFromSession();
|
||||
}
|
||||
return is_object($this->user);
|
||||
}
|
||||
|
||||
public function removeAuthorization()
|
||||
{
|
||||
$this->user = null;
|
||||
$this->session->delete();
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function getGroups()
|
||||
{
|
||||
return $this->user->getGroups();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Authentication;
|
||||
|
||||
use Icinga\Application\Logger as Logger;
|
||||
|
||||
/**
|
||||
* Class PhpSession
|
||||
*
|
||||
* Standard PHP Session handling
|
||||
* You have to call read() first in order to start the session. If
|
||||
* no parameter is given to read, the session is closed immediately
|
||||
* after reading the persisted variables, in order to avoid concurrent
|
||||
* requests to be blocked. Otherwise, you can call write() (again with
|
||||
* no parameter in order to auto-close it) to persist all values previously
|
||||
* set with the set() method
|
||||
*
|
||||
* @package Icinga\Authentication
|
||||
*/
|
||||
class PhpSession extends Session
|
||||
{
|
||||
const SESSION_NAME = "Icinga2Web";
|
||||
private $isOpen = false;
|
||||
private $isFlushed = false;
|
||||
|
||||
private static $DEFAULT_COOKIEOPTIONS = array(
|
||||
'use_trans_sid' => false,
|
||||
'use_cookies' => true,
|
||||
'use_only_cooies' => true,
|
||||
'cookie_httponly' => true,
|
||||
'use_only_cookies' => true,
|
||||
'hash_function' => true,
|
||||
'hash_bits_per_character' => 5,
|
||||
);
|
||||
|
||||
public function __construct(array $options = null)
|
||||
{
|
||||
if ($options !== null) {
|
||||
$options = array_merge(PhpSession::$DEFAULT_COOKIEOPTIONS, $options);
|
||||
} else {
|
||||
$options = PhpSession::$DEFAULT_COOKIEOPTIONS;
|
||||
}
|
||||
foreach ($options as $sessionVar => $value) {
|
||||
if (ini_set("session.".$sessionVar, $value) === false) {
|
||||
Logger::warn(
|
||||
"Could not set php.ini setting %s = %s. This might affect your sessions behaviour.",
|
||||
$sessionVar,
|
||||
$value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function sessionCanBeChanged()
|
||||
{
|
||||
if ($this->isFlushed) {
|
||||
Logger::error("Tried to work on a closed session, session changes will be ignored");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function sessionCanBeOpened()
|
||||
{
|
||||
if ($this->isOpen) {
|
||||
Logger::warn("Tried to open a session more than once");
|
||||
return false;
|
||||
}
|
||||
return $this->sessionCanBeChanged();
|
||||
}
|
||||
|
||||
public function open()
|
||||
{
|
||||
if (!$this->sessionCanBeOpened()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
session_name(PhpSession::SESSION_NAME);
|
||||
session_start();
|
||||
$this->isOpen = true;
|
||||
$this->setAll($_SESSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
private function ensureOpen()
|
||||
{
|
||||
// try to open first
|
||||
if (!$this->isOpen) {
|
||||
if (!$this->open()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function read($keepOpen = false)
|
||||
{
|
||||
if (!$this->ensureOpen) {
|
||||
return false;
|
||||
}
|
||||
if ($keepOpen) {
|
||||
return true;
|
||||
}
|
||||
$this->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
public function write($keepOpen = false)
|
||||
{
|
||||
if (!$this->ensureOpen) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->getAll() as $key => $value) {
|
||||
$_SESSION[$key] = $value;
|
||||
}
|
||||
if ($keepOpen) {
|
||||
return null;
|
||||
}
|
||||
$this->close();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
if (!$this->isFlushed) {
|
||||
session_write_close();
|
||||
}
|
||||
$this->isFlushed = true;
|
||||
}
|
||||
|
||||
public function purge()
|
||||
{
|
||||
if ($this->ensureOpen() && !$this->isFlushed) {
|
||||
$_SESSION = array();
|
||||
session_destroy();
|
||||
$this->clearCookies();
|
||||
}
|
||||
}
|
||||
|
||||
private function clearCookies()
|
||||
{
|
||||
if (ini_get("session.use_cookies")) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(
|
||||
session_name(),
|
||||
'',
|
||||
time() - 42000,
|
||||
$params["path"],
|
||||
$params["domain"],
|
||||
$params["secure"],
|
||||
$params["httponly"]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Authentication;
|
||||
|
||||
abstract class Session
|
||||
{
|
||||
private $sessionValues = array();
|
||||
|
||||
abstract public function open();
|
||||
abstract public function read($keepOpen = false);
|
||||
abstract public function write($keepOpen = false);
|
||||
abstract public function close();
|
||||
abstract public function purge();
|
||||
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->sessionValues[$key] = $value;
|
||||
}
|
||||
|
||||
public function get($key, $defaultValue = null)
|
||||
{
|
||||
return isset($this->sessionValues[$key]) ?
|
||||
$this->sessionValues[$key] : $defaultValue;
|
||||
}
|
||||
|
||||
public function getAll()
|
||||
{
|
||||
return $this->sessionValues;
|
||||
}
|
||||
|
||||
public function setAll(array $values, $overwrite = false)
|
||||
{
|
||||
if ($overwrite) {
|
||||
$this->clear();
|
||||
}
|
||||
foreach ($values as $key => $value) {
|
||||
if (isset($this->sessionValues[$key]) && !$overwrite) {
|
||||
continue;
|
||||
}
|
||||
$this->sessionValues[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
$this->sessionValues = array();
|
||||
}
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Icinga Authentication Storable class
|
||||
*
|
||||
* @package Icinga\Authentication
|
||||
*/
|
||||
namespace Icinga\Authentication;
|
||||
|
||||
/**
|
||||
* This class represents an abstract storable object
|
||||
*
|
||||
* Use this only for objects with unique identifiers. Do not persist such
|
||||
* objects, they shall be loaded at each request. Storable doesn't care about
|
||||
* race conditions and doesn't care about the current data in your backend.
|
||||
*
|
||||
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
|
||||
* @author Icinga-Web Team <info@icinga.org>
|
||||
* @package Icinga\Application
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
|
||||
*/
|
||||
abstract class Storable
|
||||
{
|
||||
protected $key;
|
||||
|
||||
/**
|
||||
* Current Storable properties
|
||||
*/
|
||||
protected $props;
|
||||
|
||||
/**
|
||||
* Default property values for this Storable
|
||||
*
|
||||
* All allowed properties have to be defined here, otherwise they will be
|
||||
* rejected
|
||||
*/
|
||||
protected $defaultProps = array();
|
||||
|
||||
/**
|
||||
* Properties as they have been once loaded from backend
|
||||
*/
|
||||
protected $storedProps = array();
|
||||
|
||||
/**
|
||||
* Whether this storable has been stored in the current state
|
||||
*/
|
||||
protected $stored = false;
|
||||
|
||||
/**
|
||||
* Create a new Storable instance, with data loaded from backend
|
||||
*
|
||||
* You should NEVER directly use this function unless you are absolutely
|
||||
* sure on what you are doing.
|
||||
*
|
||||
* @param Backend The backend used to load this object from
|
||||
* @param Array Property array
|
||||
* @return Storable
|
||||
*/
|
||||
public static function create(UserBackend $backend, $props = array())
|
||||
{
|
||||
$class = get_called_class();
|
||||
$object = new $class($props);
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this function for custom cross-value checks before storing it
|
||||
*
|
||||
* @return boolean Whether the Storable is valid
|
||||
*/
|
||||
public function isValid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor is protected, you should never override it
|
||||
*
|
||||
* Use the available hooks for all the things you need to do at construction
|
||||
* time
|
||||
*
|
||||
* @param Array Property array
|
||||
* @return void
|
||||
*/
|
||||
final protected function __construct($properties = array())
|
||||
{
|
||||
$this->assertKeyHasBeenDefined();
|
||||
$this->props = $this->defaultProps;
|
||||
foreach ($properties as $key => $val) {
|
||||
$this->set($key, $val);
|
||||
}
|
||||
$this->assertKeyExists();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get property value, fail unless it exists
|
||||
*
|
||||
* @param string Property name
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
$this->assertPropertyExists($key);
|
||||
return $this->props[$key];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set property value, fail unless it exists
|
||||
*
|
||||
* @param string Property name
|
||||
* @param mixed New property value
|
||||
* @return Storable
|
||||
*/
|
||||
protected function set($key, $val)
|
||||
{
|
||||
$this->assertPropertyExists($key);
|
||||
$this->props[$key] = $val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter
|
||||
*
|
||||
* @param string Property name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter
|
||||
*
|
||||
* @param string Property name
|
||||
* @param mixed New property value
|
||||
* @return void
|
||||
*/
|
||||
public function __set($key, $val)
|
||||
{
|
||||
$this->set($key, $val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given property name exist
|
||||
*
|
||||
* @param string Property name
|
||||
* @return boolean
|
||||
*/
|
||||
public function __isset($key)
|
||||
{
|
||||
return array_key_exists($key, $this->props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that the Storable got it's unique key
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return Storable
|
||||
*/
|
||||
protected function assertKeyExists()
|
||||
{
|
||||
return $this->assertPropertyExists($this->key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the given property is allowed
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return Storable
|
||||
*/
|
||||
protected function assertPropertyExists($key)
|
||||
{
|
||||
if (! array_key_exists($key, $this->props)) {
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'Storable (%s) has no "%s" property',
|
||||
get_class($this),
|
||||
$key
|
||||
)
|
||||
);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that the class inheriting Storable defined it's key column
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return Storable
|
||||
*/
|
||||
protected function assertKeyHasBeenDefined()
|
||||
{
|
||||
if ($this->key === null) {
|
||||
throw new \Exception(
|
||||
'Implementation error, Storable needs a valid key'
|
||||
);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
/**
|
||||
* Icinga Authentication User class
|
||||
|
@ -10,61 +12,125 @@ namespace Icinga\Authentication;
|
|||
/**
|
||||
* This class represents a user object
|
||||
*
|
||||
* TODO: Show some use cases
|
||||
*
|
||||
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
|
||||
* @author Icinga-Web Team <info@icinga.org>
|
||||
* @package Icinga\Application
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
|
||||
*/
|
||||
class User extends Storable
|
||||
class User
|
||||
{
|
||||
protected $defaultProps = array(
|
||||
'username' => null,
|
||||
'password' => null,
|
||||
'first_name' => null,
|
||||
'last_name' => null,
|
||||
'email' => null,
|
||||
);
|
||||
protected $permissions = array();
|
||||
protected $backend;
|
||||
protected $groups;
|
||||
protected $key = 'username';
|
||||
private $username = "";
|
||||
private $firstname = "";
|
||||
private $lastname = "";
|
||||
private $email = "";
|
||||
private $domain = "";
|
||||
private $additionalInformation = array();
|
||||
|
||||
public function listGroups()
|
||||
private $permissions = array();
|
||||
private $groups = array();
|
||||
|
||||
public function __construct($username, $firstname = null, $lastname = null, $email = null)
|
||||
{
|
||||
if ($this->groups === null) {
|
||||
$this->loadGroups();
|
||||
$this->setUsername($username);
|
||||
|
||||
if ($firstname !== null) {
|
||||
$this->setFirstname($firstname);
|
||||
}
|
||||
|
||||
if ($lastname !== null) {
|
||||
$this->setLastname($lastname);
|
||||
}
|
||||
|
||||
if ($email !== null) {
|
||||
$this->setEmail($email);
|
||||
}
|
||||
}
|
||||
|
||||
protected function loadGroups()
|
||||
public function getGroups()
|
||||
{
|
||||
// Whatever
|
||||
return $this->groups;
|
||||
}
|
||||
|
||||
public function setGroups(array $groups)
|
||||
{
|
||||
$this->groups = $groups;
|
||||
}
|
||||
|
||||
public function isMemberOf(Group $group)
|
||||
{
|
||||
|
||||
return in_array($group, $this->groups);
|
||||
}
|
||||
|
||||
public function getPermissionList()
|
||||
public function getPermissions()
|
||||
{
|
||||
return $this->permissions;
|
||||
}
|
||||
|
||||
public function hasPermission($uri, $permission)
|
||||
public function getUsername()
|
||||
{
|
||||
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function grantPermission($uri, $permission)
|
||||
public function setUsername($name)
|
||||
{
|
||||
|
||||
$this->username = $name;
|
||||
}
|
||||
|
||||
public function revokePermission($uri, $permission)
|
||||
public function getFirstname()
|
||||
{
|
||||
return $this->firstname;
|
||||
}
|
||||
|
||||
public function setFirstname($name)
|
||||
{
|
||||
$this->firstname = $name;
|
||||
}
|
||||
|
||||
public function getLastname()
|
||||
{
|
||||
return $this->lastname;
|
||||
}
|
||||
|
||||
public function setLastname($name)
|
||||
{
|
||||
$this->lastname = $name;
|
||||
}
|
||||
|
||||
public function getEmail()
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail($mail)
|
||||
{
|
||||
if (filter_var($mail, FILTER_VALIDATE_EMAIL)) {
|
||||
$this->mail = $mail;
|
||||
} else {
|
||||
throw new InvalidArgumentException("Invalid mail given for user $this->username: $mail");
|
||||
}
|
||||
}
|
||||
|
||||
public function setDomain($domain)
|
||||
{
|
||||
$this->domain = $domain;
|
||||
}
|
||||
|
||||
public function getDomain()
|
||||
{
|
||||
return $this->domain;
|
||||
}
|
||||
|
||||
public function setAdditional($key, $value)
|
||||
{
|
||||
$this->additionalInformation[$key] = $value;
|
||||
}
|
||||
|
||||
public function getAdditional($key)
|
||||
{
|
||||
if (isset($this->additionalInformation[$key])) {
|
||||
return $this->additionalInformation[$key];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,15 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}}
|
||||
|
||||
namespace Icinga\Authentication;
|
||||
|
||||
class UserBackend
|
||||
interface UserBackend
|
||||
{
|
||||
protected $config;
|
||||
public function __construct($config);
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->init();
|
||||
}
|
||||
public function hasUsername(Credentials $credentials);
|
||||
|
||||
protected function init()
|
||||
{
|
||||
}
|
||||
|
||||
public function hasUsername($username)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function authenticate($username, $password = null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public function authenticate(Credentials $credentials);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace Icinga\Web;
|
||||
|
||||
use Icinga\Authentication\Auth;
|
||||
use Icinga\Authentication\Manager;
|
||||
use Icinga\Application\Benchmark;
|
||||
use Icinga\Exception;
|
||||
use Icinga\Application\Config;
|
||||
|
@ -92,12 +92,6 @@ class ActionController extends ZfController
|
|||
array $invokeArgs = array()
|
||||
) {
|
||||
Benchmark::measure('Action::__construct()');
|
||||
if (Auth::getInstance()->isAuthenticated()
|
||||
&& !$this->modifiesSession
|
||||
&& !Notification::getInstance()->hasMessages()
|
||||
) {
|
||||
session_write_close();
|
||||
}
|
||||
$this->module_name = $request->getModuleName();
|
||||
$this->controller_name = $request->getControllerName();
|
||||
$this->action_name = $request->getActionName();
|
||||
|
@ -108,8 +102,13 @@ class ActionController extends ZfController
|
|||
->_setInvokeArgs($invokeArgs);
|
||||
$this->_helper = new ZfActionHelper($this);
|
||||
|
||||
if ($this->handlesAuthentication()
|
||||
|| Auth::getInstance()->isAuthenticated()
|
||||
if ($this->handlesAuthentication() ||
|
||||
Auth::getInstance(
|
||||
null,
|
||||
array(
|
||||
"writeSession" => $this->modifiesSession
|
||||
)
|
||||
)->isAuthenticated()
|
||||
) {
|
||||
$this->allowAccess = true;
|
||||
$this->init();
|
||||
|
@ -164,7 +163,7 @@ class ActionController extends ZfController
|
|||
*/
|
||||
final protected function hasPermission($uri, $permission = 'read')
|
||||
{
|
||||
return Auth::getInstance()->hasPermission($uri, $permission);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Tests\Icinga\Authentication;
|
||||
|
||||
require_once("../../library/Icinga/Authentication/Credentials.php");
|
||||
require_once("../../library/Icinga/Authentication/UserBackend.php");
|
||||
require_once("../../library/Icinga/Authentication/User.php");
|
||||
|
||||
use Icinga\Authentication\Credentials as Credentials;
|
||||
use Icinga\Authentication\UserBackend as UserBackend;
|
||||
use Icinga\Authentication\User as User;
|
||||
|
||||
/**
|
||||
* Simple backend mock that takes an config object
|
||||
* with the property "credentials", which is an array
|
||||
* of Credentials this backend authenticates
|
||||
**/
|
||||
class BackendMock implements UserBackend
|
||||
{
|
||||
public $allowedCredentials = array();
|
||||
public function __construct($config = null)
|
||||
{
|
||||
if ($config === null) {
|
||||
return;
|
||||
}
|
||||
if (isset ($config->credentials)) {
|
||||
$this->allowedCredentials = $config->credentials;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasUsername(Credentials $userCredentials)
|
||||
{
|
||||
foreach ($this->allowedCredentials as $credential) {
|
||||
if ($credential->getUsername() == $userCredentials->getUsername()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getDummyUser()
|
||||
{
|
||||
return new User(
|
||||
"Username",
|
||||
"Firstname",
|
||||
"Lastname",
|
||||
"user@test.local"
|
||||
);
|
||||
}
|
||||
|
||||
public function authenticate(Credentials $credentials)
|
||||
{
|
||||
if (!in_array($credentials, $this->allowedCredentials)) {
|
||||
return false;
|
||||
}
|
||||
return self::getDummyUser();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Icinga\Authentication;
|
||||
/**
|
||||
*
|
||||
* Test class for Credentials
|
||||
* Created Mon, 10 Jun 2013 07:54:34 +0000
|
||||
*
|
||||
**/
|
||||
class CredentialsTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Test for Credentials::GetUsername()
|
||||
*
|
||||
**/
|
||||
public function testGetUsername()
|
||||
{
|
||||
$this->markTestIncomplete('testGetUsername is not implemented yet');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Credentials::SetUsername()
|
||||
*
|
||||
**/
|
||||
public function testSetUsername()
|
||||
{
|
||||
$this->markTestIncomplete('testSetUsername is not implemented yet');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Credentials::GetPassword()
|
||||
*
|
||||
**/
|
||||
public function testGetPassword()
|
||||
{
|
||||
$this->markTestIncomplete('testGetPassword is not implemented yet');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Credentials::SetPassword()
|
||||
*
|
||||
**/
|
||||
public function testSetPassword()
|
||||
{
|
||||
$this->markTestIncomplete('testSetPassword is not implemented yet');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Credentials::GetDomain()
|
||||
*
|
||||
**/
|
||||
public function testGetDomain()
|
||||
{
|
||||
$this->markTestIncomplete('testGetDomain is not implemented yet');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for Credentials::SetDomain()
|
||||
*
|
||||
**/
|
||||
public function testSetDomain()
|
||||
{
|
||||
$this->markTestIncomplete('testSetDomain is not implemented yet');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,102 @@
|
|||
<?php
|
||||
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Tests\Icinga\Authentication;
|
||||
|
||||
/**
|
||||
*
|
||||
* Test class for Ldapuserbackend
|
||||
* Created Fri, 07 Jun 2013 10:38:16 +0000
|
||||
* Created Mon, 10 Jun 2013 07:54:34 +0000
|
||||
*
|
||||
**/
|
||||
class LdapuserbackendTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
// Change this according to your ldap test server
|
||||
const ADMIN_DN = "cn=admin,dc=icinga,dc=org";
|
||||
const ADMIN_PASS = "admin";
|
||||
|
||||
private $users = array(
|
||||
"cn=John Doe, dc=icinga, dc=org" => array(
|
||||
"cn" => "John Doe",
|
||||
"sn" => "Doe",
|
||||
"objectclass" => "inetOrgPerson",
|
||||
"givenName" => "John",
|
||||
"mail" => "john@doe.local"
|
||||
),
|
||||
"cn=Jane Woe, dc=icinga, dc=org" => array(
|
||||
"cn" => "Jane Woe",
|
||||
"sn" => "Woe",
|
||||
"objectclass" => "inetOrgPerson",
|
||||
"givenName" => "Jane",
|
||||
"mail" => "jane@woe.local"
|
||||
)
|
||||
);
|
||||
|
||||
private function getLDAPConnection()
|
||||
{
|
||||
$this->markTestSkipped("LDAP User Backend is currently not testable, as it would require to Boostrap most of the application (see Protocol\Ldap\Connection)");
|
||||
return;
|
||||
$ldapConn = ldap_connect("localhost", 389);
|
||||
if (!$ldapConn) {
|
||||
$this->markTestSkipped("Could not connect to test-ldap server, skipping test");
|
||||
return null;
|
||||
}
|
||||
$bind = ldap_bind($ldapConn, self::ADMIN_DN, self::ADMIN_PASS);
|
||||
if (!$bind) {
|
||||
$this->markTestSkipped("Could not bind to test-ldap server, skipping test");
|
||||
return null;
|
||||
}
|
||||
return $ldapConn;
|
||||
}
|
||||
|
||||
private function clearTestData($connection)
|
||||
{
|
||||
foreach ($this->users as $ou => $info) {
|
||||
@ldap_delete($connection, $ou);
|
||||
}
|
||||
}
|
||||
|
||||
private function insertTestdata($connection)
|
||||
{
|
||||
foreach ($this->users as $ou => $info) {
|
||||
if (ldap_add($connection, $ou, $info) === false) {
|
||||
$this->markTestSkipped("Couldn't set up test-ldap users, skipping test");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$conn = $this->getLDAPConnection();
|
||||
if ($conn == null) {
|
||||
return;
|
||||
}
|
||||
$this->clearTestData($conn);
|
||||
$this->insertTestData($conn);
|
||||
$result = ldap_list($conn, "dc=icinga, dc=org", "(cn=John Doe)");
|
||||
if (ldap_count_entries($conn, $result) < 1) {
|
||||
$this->markTestSkipped("Couldn't set up test users, skipping test");
|
||||
}
|
||||
$result = ldap_list($conn, "dc=icinga, dc=org", "(cn=Jane Woe)");
|
||||
if (ldap_count_entries($conn, $result) < 1) {
|
||||
$this->markTestSkipped("Couldn't set up test users, skipping test");
|
||||
}
|
||||
ldap_close($conn);
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$conn = $this->getLDAPConnection();
|
||||
if ($conn == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->clearTestData($conn);
|
||||
ldap_close($conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for LdapUserBackend::HasUsername()
|
||||
|
@ -16,7 +104,6 @@ class LdapuserbackendTest extends \PHPUnit_Framework_TestCase
|
|||
**/
|
||||
public function testHasUsername()
|
||||
{
|
||||
$this->markTestIncomplete('testHasUsername is not implemented yet');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,5 +114,4 @@ class LdapuserbackendTest extends \PHPUnit_Framework_TestCase
|
|||
{
|
||||
$this->markTestIncomplete('testAuthenticate is not implemented yet');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Tests\Icinga\Authentication;
|
||||
|
||||
require_once("../../library/Icinga/Application/Logger.php");
|
||||
require_once("../../library/Icinga/Authentication/Manager.php");
|
||||
require_once("../../library/Icinga/Authentication/Credentials.php");
|
||||
require_once("Zend/Log.php");
|
||||
require_once("BackendMock.php");
|
||||
require_once("SessionMock.php");
|
||||
|
||||
use Icinga\Authentication\Manager as AuthManager;
|
||||
use Icinga\Authentication\Credentials as Credentials;
|
||||
|
||||
/**
|
||||
*
|
||||
* Test class for Manager
|
||||
* Created Mon, 10 Jun 2013 07:54:34 +0000
|
||||
*
|
||||
**/
|
||||
class ManagerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getTestCredentials()
|
||||
{
|
||||
return (object) array("credentials" => array(
|
||||
new Credentials("jdoe", "passjdoe"),
|
||||
new Credentials("root", "passroot"),
|
||||
new Credentials("test", "passtest")
|
||||
));
|
||||
}
|
||||
|
||||
public function getManagerInstance(&$session = null, $write = false)
|
||||
{
|
||||
if ($session == null) {
|
||||
$session = new SessionMock();
|
||||
}
|
||||
return AuthManager::getInstance(
|
||||
(object) array(),
|
||||
array(
|
||||
"userBackendClass" => new BackendMock(
|
||||
$this->getTestCredentials()
|
||||
),
|
||||
"groupBackendClass" => new BackendMock(),
|
||||
"sessionClass" => $session,
|
||||
"writeSession" => $write
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testManagerInstanciation()
|
||||
{
|
||||
AuthManager::clearInstance();
|
||||
$this->setPreserveGlobalState(false);
|
||||
$authMgr = $this->getManagerInstance();
|
||||
$auth = $this->assertEquals($authMgr, AuthManager::getInstance());
|
||||
AuthManager::clearInstance();
|
||||
}
|
||||
|
||||
|
||||
public function testAuthentication()
|
||||
{
|
||||
AuthManager::clearInstance();
|
||||
$auth = $this->getManagerInstance();
|
||||
$this->assertFalse(
|
||||
$auth->authenticate(
|
||||
new Credentials("jhoe", "passjdoe"),
|
||||
false
|
||||
)
|
||||
);
|
||||
$this->assertFalse(
|
||||
$auth->authenticate(
|
||||
new Credentials("joe", "passjhoe"),
|
||||
false
|
||||
)
|
||||
);
|
||||
$this->assertTrue(
|
||||
$auth->authenticate(
|
||||
new Credentials("jdoe", "passjdoe"),
|
||||
false
|
||||
)
|
||||
);
|
||||
AuthManager::clearInstance();
|
||||
}
|
||||
|
||||
public function testPersistAuthInSession()
|
||||
{
|
||||
AuthManager::clearInstance();
|
||||
$session = new SessionMock();
|
||||
$auth = $this->getManagerInstance($session, true);
|
||||
$this->assertFalse($auth->isAuthenticated(true));
|
||||
$auth->authenticate(new Credentials("jdoe", "passjdoe"));
|
||||
$this->assertNotEquals(null, $session->get("user"));
|
||||
$user = $session->get("user");
|
||||
$this->assertEquals("Username", $user->getUsername());
|
||||
$this->assertTrue($auth->isAuthenticated(true));
|
||||
AuthManager::clearInstance();
|
||||
}
|
||||
|
||||
public function testAuthenticateFromSession()
|
||||
{
|
||||
AuthManager::clearInstance();
|
||||
$session = new SessionMock();
|
||||
$session->set("user", BackendMock::getDummyUser());
|
||||
$auth = $this->getManagerInstance($session, false);
|
||||
$this->assertFalse($auth->isAuthenticated(true));
|
||||
$this->assertTrue($auth->isAuthenticated());
|
||||
$this->assertTrue($auth->isAuthenticated());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @expectedException \Exception
|
||||
**/
|
||||
public function testWriteSessionTwice()
|
||||
{
|
||||
$auth = $this->getManagerInstance($session, false);
|
||||
$this->assertFalse($auth->isAuthenticated(true));
|
||||
$auth->authenticate(new Credentials("jdoe", "passjdoe"));
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Tests\Icinga\Authentication;
|
||||
|
||||
require_once("../../library/Icinga/Authentication/Session.php");
|
||||
require_once("../../library/Icinga/Authentication/PhpSession.php");
|
||||
require_once("../../library/Icinga/Application/Logger.php");
|
||||
require_once("Zend/Log.php");
|
||||
|
||||
use Icinga\Authentication\PhpSession as PhpSession;
|
||||
|
||||
class PHPSessionTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
**/
|
||||
public function testSessionCreation()
|
||||
{
|
||||
$session = new PhpSession();
|
||||
$session = new PhpSession(array("ssesion.use_cookies"=>false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
**/
|
||||
public function testOpenSession()
|
||||
{
|
||||
$this->assertEquals(session_id(), '');
|
||||
$session = new PhpSession();
|
||||
$session->open();
|
||||
$this->assertNotEquals(session_id(), '');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
**/
|
||||
public function testCloseSession()
|
||||
{
|
||||
|
||||
$this->assertEquals(session_id(), '');
|
||||
$session = new PhpSession();
|
||||
$session->open();
|
||||
$this->assertNotEquals(session_id(), '');
|
||||
$session->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
**/
|
||||
public function testPurgeSession()
|
||||
{
|
||||
$this->assertEquals(session_id(), '');
|
||||
$session = new PhpSession();
|
||||
$session->open();
|
||||
$this->assertNotEquals(session_id(), '');
|
||||
$session->purge();
|
||||
$this->assertEquals(session_id(), '');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Tests\Icinga\Authentication;
|
||||
|
||||
require_once("../../library/Icinga/Authentication/Session.php");
|
||||
|
||||
use Icinga\Authentication\Session as Session;
|
||||
|
||||
class SessionMock extends Session
|
||||
{
|
||||
public $isOpen = false;
|
||||
public $isWritten = false;
|
||||
|
||||
public function open()
|
||||
{
|
||||
if (!$this->isOpen && $this->isWritten) {
|
||||
throw new \Exception("Session write after close");
|
||||
}
|
||||
$this->isOpen = true;
|
||||
}
|
||||
|
||||
public function read($keepOpen = false)
|
||||
{
|
||||
$this->open();
|
||||
if (!$keepOpen) {
|
||||
$this->close();
|
||||
}
|
||||
}
|
||||
|
||||
public function write($keepOpen = false)
|
||||
{
|
||||
|
||||
$this->open();
|
||||
if (!$keepOpen) {
|
||||
$this->close();
|
||||
}
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
$this->isOpen = false;
|
||||
$this->isWritten = true;
|
||||
}
|
||||
|
||||
public function purge()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -6,7 +6,10 @@ require_once("../../library/Icinga/Protocol/Statusdat/Reader.php");
|
|||
require_once("../../library/Icinga/Exception/ConfigurationError.php");
|
||||
|
||||
use Icinga\Protocol\Statusdat\Reader as Reader;
|
||||
define("APPLICATION_PATH","./"); // TODO: test boostrap
|
||||
|
||||
if (!defined('APPLICATION_PATH')) {
|
||||
define("APPLICATION_PATH","./"); // TODO: test boostrap
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Test class for Reader
|
||||
|
|
Loading…
Reference in New Issue