* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Cyrsql class provides a SQL implementation of the Horde
* authentication system for the Cyrus IMAP server. Most of the functionality
* is the same as for the SQL class; only what is different overrides the
* parent class implementations.
*
* The table structure for the auth system is as follows:
*
* CREATE TABLE accountuser (
* username VARCHAR(255) BINARY NOT NULL DEFAULT '',
* password VARCHAR(32) BINARY NOT NULL DEFAULT '',
* prefix VARCHAR(50) NOT NULL DEFAULT '',
* domain_name VARCHAR(255) NOT NULL DEFAULT '',
* UNIQUE KEY username (username)
* );
*
* CREATE TABLE adminuser (
* username VARCHAR(50) BINARY NOT NULL DEFAULT '',
* password VARCHAR(50) BINARY NOT NULL DEFAULT '',
* type INT(11) NOT NULL DEFAULT '0',
* SID VARCHAR(255) NOT NULL DEFAULT '',
* home VARCHAR(255) NOT NULL DEFAULT '',
* PRIMARY KEY (username)
* );
*
* CREATE TABLE alias (
* alias VARCHAR(255) NOT NULL DEFAULT '',
* dest LONGTEXT,
* username VARCHAR(50) NOT NULL DEFAULT '',
* status INT(11) NOT NULL DEFAULT '1',
* PRIMARY KEY (alias)
* );
*
* CREATE TABLE domain (
* domain_name VARCHAR(255) NOT NULL DEFAULT '',
* prefix VARCHAR(50) NOT NULL DEFAULT '',
* maxaccounts INT(11) NOT NULL DEFAULT '20',
* quota INT(10) NOT NULL DEFAULT '20000',
* transport VARCHAR(255) NOT NULL DEFAULT 'cyrus',
* freenames ENUM('YES','NO') NOT NULL DEFAULT 'NO',
* freeaddress ENUM('YES','NO') NOT NULL DEFAULT 'NO',
* PRIMARY KEY (domain_name),
* UNIQUE KEY prefix (prefix)
* );
*
* CREATE TABLE domainadmin (
* domain_name VARCHAR(255) NOT NULL DEFAULT '',
* adminuser VARCHAR(255) NOT NULL DEFAULT ''
* );
*
* CREATE TABLE search (
* search_id VARCHAR(255) NOT NULL DEFAULT '',
* search_sql TEXT NOT NULL,
* perpage INT(11) NOT NULL DEFAULT '0',
* timestamp TIMESTAMP(14) NOT NULL,
* PRIMARY KEY (search_id),
* KEY search_id (search_id)
* );
*
* CREATE TABLE virtual (
* alias VARCHAR(255) NOT NULL DEFAULT '',
* dest LONGTEXT,
* username VARCHAR(50) NOT NULL DEFAULT '',
* status INT(11) NOT NULL DEFAULT '1',
* KEY alias (alias)
* );
*
* CREATE TABLE log (
* id INT(11) NOT NULL AUTO_INCREMENT,
* msg TEXT NOT NULL,
* user VARCHAR(255) NOT NULL DEFAULT '',
* host VARCHAR(255) NOT NULL DEFAULT '',
* time DATETIME NOT NULL DEFAULT '2000-00-00 00:00:00',
* pid VARCHAR(255) NOT NULL DEFAULT '',
* PRIMARY KEY (id)
* );
*
*
* @author Ilya Krel
* @author Jan Schneider
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Cyrsql extends Horde_Auth_Sql
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'add' => true,
'list' => true,
'remove' => true,
'resetpassword' => false,
'update' => true,
'authenticate' => true,
);
/**
* Horde_Imap_Client object.
*
* @var Horde_Imap_Client_Base
*/
protected $_imap;
/**
* Constructor.
*
* @param array $params Parameters:
* - domain_field: (string) If set to anything other than 'none' this is
* used as field name where domain is stored.
* DEFAULT: 'domain_name'
* - folders: (array) An array of folders to create under username.
* DEFAULT: NONE
* - hidden_accounts: (array) An array of system accounts to hide from
* the user interface.
* DEFAULT: None.
* - imap: (Horde_Imap_Client_Base) [REQUIRED] An IMAP client object.
* - quota: (integer) The quota (in kilobytes) to grant on the mailbox.
* DEFAULT: NONE
* - userhierarchy: (string) The user hierarchy prefix (UTF-8).
* DEFAULT: 'user.'
*
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
if (!isset($params['imap']) ||
!($params['imap'] instanceof Horde_Imap_Client_Base)) {
throw new InvalidArgumentException('Missing imap parameter.');
}
$this->_imap = $params['imap'];
unset($params['imap']);
$params = array_merge(array(
'domain_field' => 'domain_name',
'folders' => array(),
'hidden_accounts' => array('cyrus'),
'quota' => null,
'userhierarchy' => 'user.'
), $params);
parent::__construct($params);
}
/**
* Find out if a set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials The credentials to use.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
if (!empty($this->_params['domain_field']) &&
($this->_params['domain_field'] != 'none')) {
/* Build the SQL query with domain. */
$query = sprintf('SELECT * FROM %s WHERE %s = ? AND %s = ?',
$this->_params['table'],
$this->_params['username_field'],
$this->_params['domain_field']);
$values = explode('@', $userId);
} else {
/* Build the SQL query without domain. */
$query = sprintf('SELECT * FROM %s WHERE %s = ?',
$this->_params['table'],
$this->_params['username_field']);
$values = array($userId);
}
try {
$row = $this->_db->selectOne($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_FAILED);
}
if (!$row ||
!$this->_comparePasswords($row[$this->_params['password_field']], $credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
$now = time();
if (!empty($this->_params['hard_expiration_field']) &&
!empty($row[$this->_params['hard_expiration_field']]) &&
($now > $row[$this->_params['hard_expiration_field']])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_EXPIRED);
}
if (!empty($this->_params['soft_expiration_field']) &&
!empty($row[$this->_params['soft_expiration_field']]) &&
($now > $row[$this->_params['soft_expiration_field']])) {
$this->setCredential('change', true);
}
}
/**
* Add a set of authentication credentials.
*
* @param string $userId The userId to add.
* @param array $credentials The credentials to add.
*
* @throw Horde_Auth_Exception
*/
public function addUser($userId, $credentials)
{
if (!empty($this->_params['domain_field']) &&
($this->_params['domain_field'] != 'none')) {
list($name, $domain) = explode('@', $userId);
$query = sprintf('INSERT INTO %s (%s, %s, %s) VALUES (?, ?, ?)',
$this->_params['table'],
$this->_params['username_field'],
$this->_params['domain_field'],
$this->_params['password_field']);
$values = array(
$name,
$domain,
Horde_Auth::getCryptedPassword($credentials['password'],
'',
$this->_params['encryption'],
$this->_params['show_encryption'])
);
$query2 = 'INSERT INTO virtual (alias, dest, username, status) VALUES (?, ?, ?, 1)';
$values2 = array($userId, $userId, $name);
try {
$this->_db->insert($query, $values);
$this->_db->insert($query2, $values2);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception($e);
}
} else {
parent::addUser($userId, $credentials);
}
$mailbox = $this->_params['userhierarchy'];
try {
$this->_imap->createMailbox($mailbox);
$this->_imap->setACL($mailbox, $this->_params['cyradmin'], array('rights' => 'lrswipcda'));
if (isset($this->_params['quota']) &&
($this->_params['quota'] >= 0)) {
$this->_imap->setQuota($mailbox, array('storage' => $this->_params['quota']));
}
} catch (Horde_Imap_Client_Exception $e) {
throw new Horde_Auth_Exception($e);
}
foreach ($this->_params['folders'] as $val) {
try {
$this->_imap->createMailbox($val);
$this->_imap->setACL($val, $this->_params['cyradmin'], array('rights' => 'lrswipcda'));
} catch (Horde_Imap_Client_Exception $e) {}
}
}
/**
* Delete a set of authentication credentials.
*
* @param string $userId The userId to delete.
*
* @throws Horde_Auth_Exception
*/
public function removeUser($userId)
{
if (!empty($this->_params['domain_field']) &&
($this->_params['domain_field'] != 'none')) {
list($name, $domain) = explode('@', $userId);
/* Build the SQL query. */
$query = sprintf('DELETE FROM %s WHERE %s = ? and %s = ?',
$this->_params['table'],
$this->_params['username_field'],
$this->_params['domain_field']);
$values = array($name, $domain);
$query2 = 'DELETE FROM virtual WHERE dest = ?';
$values2 = array($userId);
try {
$this->_db->delete($query, $values);
$this->_db->delete($query2, $values2);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception($e);
}
} else {
parent::removeUser($userId);
}
/* Set ACL for mailbox deletion. */
list($admin) = explode('@', $this->_params['cyradmin']);
$mailbox = $this->_params['userhierarchy'];
try {
$this->_imap->setACL($mailbox, $admin, array('rights' => 'lrswipcda'));
$this->_imap->deleteMailbox($mailbox);
} catch (Horde_Imap_Client_Exception $e) {
throw new Horde_Auth_Exception($e);
}
}
/**
* List all users in the system.
*
* @param boolean $sort Sort the users?
*
* @return mixed The array of userIds.
* @throws Horde_Auth_Exception
*/
public function listUsers($sort = false)
{
if (!empty($this->_params['domain_field']) &&
($this->_params['domain_field'] != 'none')) {
/* Build the SQL query with domain. */
$query = sprintf('SELECT %s, %s FROM %s',
$this->_params['username_field'],
$this->_params['domain_field'],
$this->_params['table']);
} else {
/* Build the SQL query without domain. */
$query = sprintf('SELECT %s FROM %s',
$this->_params['username_field'],
$this->_params['table']);
}
if ($sort) {
$query .= sprintf(" ORDER BY %s", $this->_params['username_field']);
}
try {
$result = $this->_db->selectAll($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception($e);
}
/* Loop through and build return array. */
$users = array();
if (!empty($this->_params['domain_field']) &&
($this->_params['domain_field'] != 'none')) {
foreach ($result as $ar) {
if (!in_array($ar[$this->_params['username_field']], $this->_params['hidden_accounts'])) {
$users[] = $ar[$this->_params['username_field']] . '@' . $ar[$this->_params['domain_field']];
}
}
} else {
foreach ($result as $ar) {
if (!in_array($ar[$this->_params['username_field']], $this->_params['hidden_accounts'])) {
$users[] = $ar[$this->_params['username_field']];
}
}
}
return $users;
}
/**
* Update a set of authentication credentials.
*
* @param string $oldID The old userId.
* @param string $newID The new userId. [NOT SUPPORTED]
* @param array $credentials The new credentials
*
* @throws Horde_Auth_Exception
*/
public function updateUser($oldID, $newID, $credentials)
{
if (!empty($this->_params['domain_field']) &&
($this->_params['domain_field'] != 'none')) {
list($name, $domain) = explode('@', $oldID);
/* Build the SQL query with domain. */
$query = sprintf(
'UPDATE %s SET %s = ? WHERE %s = ? and %s = ?',
$this->_params['table'],
$this->_params['password_field'],
$this->_params['username_field'],
$this->_params['domain_field']
);
$values = array(
Horde_Auth::getCryptedPassword($credentials['password'], '', $this->_params['encryption'], $this->_params['show_encryption']),
$name,
$domain
);
} else {
/* Build the SQL query. */
$query = sprintf(
'UPDATE %s SET %s = ? WHERE %s = ?',
$this->_params['table'],
$this->_params['password_field'],
$this->_params['username_field']
);
$values = array(
Horde_Auth::getCryptedPassword($credentials['password'], '', $this->_params['encryption'], $this->_params['show_encryption']),
$oldID
);
}
try {
$this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception($e);
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Exception.php 0000664 0001750 0001750 00000001322 12653661601 017105 0 ustar jan jan
* @author Michael Slusarz
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* Exception class for the Horde_Auth package.
*
* @author Chuck Hagenbuch
* @author Michael Slusarz
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Exception extends Horde_Exception_Wrapped
{
}
Horde_Auth-2.1.11/lib/Horde/Auth/Ftp.php 0000664 0001750 0001750 00000004255 12653661601 015710 0 ustar jan jan
* @author Max Kalika
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Ftp class provides an FTP implementation of the Horde
* authentication system.
*
* @author Chuck Hagenbuch
* @author Max Kalika
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Ftp extends Horde_Auth_Base
{
/**
* Constructor.
*
* @param array $params Optional parameters:
*
* 'hostspec' - (string) The hostname or IP address of the FTP server.
* DEFAULT: 'localhost'
* 'port' - (integer) The server port to connect to.
* DEFAULT: 21
*
*
* @throws Horde_Auth_Exception
*/
public function __construct(array $params = array())
{
if (!Horde_Util::extensionExists('ftp')) {
throw new Horde_Auth_Exception(__CLASS__ . ': Required FTP extension not found. Compile PHP with the --enable-ftp switch.');
}
$params = array_merge(array(
'hostspec' => 'localhost',
'port' => 21
), $params);
parent::__construct($params);
}
/**
* Find out if a set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials. For FTP,
* this must contain a password entry.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
$ftp = @ftp_connect($this->_params['hostspec'], $this->_params['port']);
$res = $ftp && @ftp_login($ftp, $userId, $credentials['password']);
@ftp_quit($ftp);
if ($res) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Http.php 0000664 0001750 0001750 00000010052 12653661601 016066 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Http class transparently logs users in to Horde using
* already present HTTP authentication headers.
*
* @author Chuck Hagenbuch
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Http extends Horde_Auth_Base
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'transparent' => true
);
/**
* Array of usernames and hashed passwords.
*
* @var array
*/
protected $_users = array();
/**
* Constructor.
*
* @param array $params Optional parameters:
*
* 'encryption' - (string) Kind of passwords in the .htpasswd file.
* Either 'crypt-des' (standard crypted htpasswd entries)
* [DEFAULT] or 'aprmd5'. This information is used if
* you want to directly authenticate users with this
* driver, instead of relying on transparent auth.
* 'htpasswd_file' - (string) TODO
*
*/
public function __construct(array $params = array())
{
$params = array_merge(array(
'encryption' => 'crypt-des'
), $params);
parent::__construct($params);
if (!empty($this->_params['htpasswd_file'])) {
$users = file($this->_params['htpasswd_file']);
if (is_array($users)) {
// Enable the list users capability.
$this->_capabilities['list'] = true;
foreach ($users as $line) {
list($user, $pass) = explode(':', $line, 2);
$this->_users[trim($user)] = trim($pass);
}
}
}
}
/**
* Find out if a set of login credentials are valid. Only supports
* htpasswd files with DES passwords right now.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials. For IMAP,
* this must contain a password entry.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
if (empty($credentials['password']) ||
empty($this->_users[$userId])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
$hash = Horde_Auth::getCryptedPassword($credentials['password'], $this->_users[$userId], $this->_params['encryption'], !empty($this->_params['show_encryption']));
if ($hash != $this->_users[$userId]) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
}
/**
* Lists all users in the system.
*
* @param boolean $sort Sort the users?
*
* @return array The array of userIds.
*/
public function listUsers($sort = false)
{
// this driver sorts by default
$users = array_keys($this->_users);
return $this->_sort($users, $sort);
}
/**
* Automatic authentication: Find out if the client has HTTP
* authentication info present.
*
* @return boolean Whether or not the client is allowed.
*/
public function transparent()
{
if (empty($_SERVER['PHP_AUTH_USER']) ||
empty($_SERVER['PHP_AUTH_PW'])) {
return false;
}
$this->_credentials['userId'] = $_SERVER['PHP_AUTH_USER'];
$this->_credentials['credentials'] = array(
'password' => Horde_Util::dispelMagicQuotes($_SERVER['PHP_AUTH_PW'])
);
return true;
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Imap.php 0000664 0001750 0001750 00000015270 12653661601 016044 0 ustar jan jan
* @author Gaudenz Steinlin
* @author Jan Schneider
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Imap:: class provides an IMAP implementation of the Horde
* authentication system.
*
* @author Chuck Hagenbuch
* @author Gaudenz Steinlin
* @author Jan Schneider
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Imap extends Horde_Auth_Base
{
/**
* Imap client objects.
*
* @var array()
*/
protected $_imap = array();
/**
* Constructor.
*
* @param array $params Optional parameters:
* - admin_password: (string) The password of the administrator.
* DEFAULT: null
* - admin_user: (string) The name of a user with admin privileges.
* DEFAULT: null
* - hostspec: (string) The hostname or IP address of the server.
* DEFAULT: 'localhost'
* - port: (integer) The server port to which we will connect.
* IMAP is generally 143, while IMAP-SSL is generally 993.
* DEFAULT: Encryption port default
* - secure: (string) The encryption to use. Either 'none', 'ssl', or
* 'tls'.
* DEFAULT: 'none'
* - userhierarchy: (string) The hierarchy where user mailboxes are
* stored (UTF-8).
* DEFAULT: 'user.'
*/
public function __construct(array $params = array())
{
$params = array_merge(array(
'admin_password' => null,
'admin_user' => null,
'hostspec' => '',
'port' => null,
'secure' => 'none',
'userhierarchy' => 'user.'
), $params);
parent::__construct($params);
if (!empty($this->_params['admin_user'])) {
$this->_capabilities = array_merge($this->_capabilities, array(
'add' => true,
'list' => true,
'remove' => true
));
}
}
/**
* Find out if a set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials. For IMAP,
* this must contain a password entry.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
try {
$ob = $this->_getOb($userId, $credentials['password']);
$ob->login();
} catch (Horde_Imap_Client_Exception $e) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
}
/**
* Add a set of authentication credentials.
*
* @param string $userId The userId to add.
* @param array $credentials The credentials to use.
*
* @throws Horde_Auth_Exception
*/
public function addUser($userId, $credentials)
{
if (!$this->hasCapability('add')) {
throw new Horde_Auth_Exception('Adding of users is not supported.');
}
try {
$ob = $this->_getOb($this->_params['admin_user'], $this->_params['admin_password']);
$name = $this->_params['userhierarchy'] . $userId;
$ob->createMailbox($name);
$ob->setACL($name, $this->_params['admin_user'], array(
'rights' => 'lrswipcda'
));
} catch (Horde_Imap_Client_Exception $e) {
throw new Horde_Auth_Exception($e);
}
}
/**
* Delete a set of authentication credentials.
*
* @param string $userId The userId to delete.
*
* @throws Horde_Auth_Exception
*/
public function removeUser($userId)
{
if (!$this->hasCapability('remove')) {
throw new Horde_Auth_Exception('Removing of users is not supported.');
}
try {
$ob = $this->_getOb($this->_params['admin_user'], $this->_params['admin_password']);
$name = $this->_params['userhierarchy'] . $userId;
$ob->setACL($name, $this->_params['admin_user'], array(
'rights' => 'lrswipcda'
));
$ob->deleteMailbox($name);
} catch (Horde_Imap_Client_Exception $e) {
throw new Horde_Auth_Exception($e);
}
}
/**
* Lists all users in the system.
*
* @param boolean $sort Sort the users?
*
* @return array The array of userIds.
* @throws Horde_Auth_Exception
*/
public function listUsers($sort = false)
{
if (!$this->hasCapability('list')) {
throw new Horde_Auth_Exception('Listing of users is not supported.');
}
try {
$ob = $this->_getOb($this->_params['admin_user'], $this->_params['admin_password']);
$list = $ob->listMailboxes($this->_params['userhierarchy'] . '%', Horde_Imap_Client::MBOX_ALL, array('flat' => true));
} catch (Horde_Imap_Client_Exception $e) {
throw new Horde_Auth_Exception($e);
}
$users = empty($list)
? array()
: preg_replace('/.*' . preg_quote($this->_params['userhierarchy'], '/') . '(.*)/', '\\1', $list);
return $this->_sort($users, $sort);
}
/**
* Get Horde_Imap_Client object.
*
* @param string $user Username.
* @param string $pass Password.
*
* @return Horde_Imap_Client_Base IMAP client object.
* @throws Horde_Auth_Exception
*/
protected function _getOb($user, $pass)
{
$sig = hash('md5', serialize(array($user, $pass)));
if (!isset($this->_ob[$sig])) {
$imap_config = array(
'hostspec' => empty($this->_params['hostspec']) ? null : $this->_params['hostspec'],
'password' => $pass,
'port' => empty($this->_params['port']) ? null : $this->_params['port'],
'secure' => ($this->_params['secure'] == 'none') ? null : $this->_params['secure'],
'username' => $user
);
try {
$this->_ob[$sig] = new Horde_Imap_Client_Socket($imap_config);
} catch (InvalidArgumentException $e) {
throw new Horde_Auth_Exception($e);
}
}
return $this->_ob[$sig];
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Ipbasic.php 0000664 0001750 0001750 00000006003 12653661601 016522 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Ipbasic class provides access control based on CIDR masks
* (client IP addresses).
*
* It is not meant for user-based systems, but for times when you want a block
* of IPs to be able to access a site, and that access is simply on/off - no
* preferences, etc.
*
* @author Chuck Hagenbuch
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Ipbasic extends Horde_Auth_Base
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'transparent' => true
);
/**
* Constructor.
*
* @param array $params Optional Parameters:
*
* 'blocks' - (array) CIDR masks which are allowed access.
*
*/
public function __construct(array $params = array())
{
if (empty($params['blocks'])) {
$params['blocks'] = array();
} elseif (!is_array($params['blocks'])) {
$params['blocks'] = array($params['blocks']);
}
parent::__construct($params);
}
/**
* Automatic authentication: Find out if the client matches an allowed IP
* block.
*
* @return boolean Whether or not the client is allowed.
*/
public function transparent()
{
if (!isset($_SERVER['REMOTE_ADDR'])) {
return false;
}
foreach ($this->_params['blocks'] as $cidr) {
if ($this->_addressWithinCIDR($_SERVER['REMOTE_ADDR'], $cidr)) {
$this->_credentials['userId'] = $cidr;
return true;
}
}
return false;
}
/**
* Not implemented
*
* @param string $userId The userID to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
throw new Horde_Auth_Exception('Unsupported.');
}
/**
* Determine if an IP address is within a CIDR block.
*
* @param string $address The IP address to check.
* @param string $cidr The block (e.g. 192.168.0.0/16) to test against.
*
* @return boolean Whether or not the address matches the mask.
*/
protected function _addressWithinCIDR($address, $cidr)
{
$address = ip2long($address);
list($quad, $bits) = explode('/', $cidr);
$bits = intval($bits);
$quad = ip2long($quad);
return (($address >> (32 - $bits)) == ($quad >> (32 - $bits)));
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Kolab.php 0000664 0001750 0001750 00000005432 12653661601 016205 0 ustar jan jan
* Copyright 2008-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you did
* not receive this file, http://www.horde.org/licenses/lgpl21
*
* @author Stuart Binge
* @author Gunnar Wrobel
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Kolab implementation of the Horde authentication system.
* Derives from the Horde_Auth_Imap authentication object, and provides
* parameters to it based on the global Kolab configuration.
*
* @author Stuart Binge
* @author Gunnar Wrobel
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Kolab extends Horde_Auth_Base
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'authenticate' => true
);
/**
* Constructor.
*
* @param array $params Parameters:
*
* 'kolab' - (Horde_Kolab_Session) [REQUIRED] TODO
*
*
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
if (!isset($params['kolab'])) {
throw new InvalidArgumentException('Missing kolab parameter.');
}
parent::__construct($params);
}
/**
* Find out if a set of login credentials are valid.
*
* For Kolab this requires to identify the IMAP server the user should
* be authenticated against before the credentials can be checked using
* this server. The Kolab_Server module handles identification of the
* correct IMAP server.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials. For Kolab,
* this must contain a "password" entry.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
try {
$this->_params['kolab']->connect($userId, $credentials);
} catch (Horde_Kolab_Session_Exception_Badlogin $e) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
} catch (Horde_Kolab_Session_Exception $e) {
if ($this->_logger) {
$this->_logger->log($e, 'ERR');
}
throw new Horde_Auth_Exception('', Horde_Auth::REASON_FAILED);
}
$this->_credentials['userId'] = $this->_params['kolab']->getMail();
return true;
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Ldap.php 0000664 0001750 0001750 00000044765 12653661601 016051 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Ldap class provides an LDAP implementation of the Horde
* authentication system.
*
* 'preauthenticate' hook should return LDAP connection information in the
* 'ldap' credentials key.
*
* @author Jon Parise
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Ldap extends Horde_Auth_Base
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'add' => true,
'update' => true,
'resetpassword' => true,
'remove' => true,
'list' => true,
'authenticate' => true,
);
/**
* LDAP object
*
* @var Horde_Ldap
*/
protected $_ldap;
/**
* Constructor.
*
* @param array $params Required parameters:
*
* 'basedn' - (string) [REQUIRED] The base DN for the LDAP server.
* 'filter' - (string) The LDAP formatted search filter to search for
* users. This setting overrides the 'objectclass' parameter.
* 'ldap' - (Horde_Ldap) [REQUIRED] Horde LDAP object.
* 'objectclass - (string|array): The objectclass filter used to search
* for users. Either a single or an array of objectclasses.
* 'uid' - (string) [REQUIRED] The username search key.
*
*
* @throws Horde_Auth_Exception
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
foreach (array('basedn', 'ldap', 'uid') as $val) {
if (!isset($params[$val])) {
throw new InvalidArgumentException(__CLASS__ . ': Missing ' . $val . ' parameter.');
}
}
if (!empty($params['ad'])) {
$this->_capabilities['resetpassword'] = false;
}
$this->_ldap = $params['ldap'];
unset($params['ldap']);
parent::__construct($params);
}
/**
* Checks for shadowLastChange and shadowMin/Max support and returns their
* values. We will also check for pwdLastSet if Active Directory is
* support is requested. For this check to succeed we need to be bound
* to the directory.
*
* @param string $dn The dn of the user.
*
* @return array Array with keys being "shadowlastchange", "shadowmin"
* "shadowmax", "shadowwarning" and containing their
* respective values or false for no support.
*/
protected function _lookupShadow($dn)
{
/* Init the return array. */
$lookupshadow = array(
'shadowlastchange' => false,
'shadowmin' => false,
'shadowmax' => false,
'shadowwarning' => false
);
/* According to LDAP standard, to read operational attributes, you
* must request them explicitly. Attributes involved in password
* expiration policy:
* pwdlastset: Active Directory
* shadow*: shadowUser schema
* passwordexpirationtime: Sun and Fedora Directory Server */
try {
$result = $this->_ldap->search(null, '(objectClass=*)', array(
'attributes' => array(
'pwdlastset',
'shadowmax',
'shadowmin',
'shadowlastchange',
'shadowwarning',
'passwordexpirationtime'
),
'scope' => 'base'
));
} catch (Horde_Ldap_Exception $e) {
return $lookupshadow;
}
if (!$result) {
return $lookupshadow;
}
$info = reset($result);
// TODO: 'ad'?
if (!empty($this->_params['ad'])) {
if (isset($info['pwdlastset'][0])) {
/* Active Directory handles timestamps a bit differently.
* Convert the timestamp to a UNIX timestamp. */
$lookupshadow['shadowlastchange'] = floor((($info['pwdlastset'][0] / 10000000) - 11644406783) / 86400) - 1;
/* Password expiry attributes are in a policy. We cannot
* read them so use the Horde config. */
$lookupshadow['shadowwarning'] = $this->_params['warnage'];
$lookupshadow['shadowmin'] = $this->_params['minage'];
$lookupshadow['shadowmax'] = $this->_params['maxage'];
}
} elseif (isset($info['passwordexpirationtime'][0])) {
/* Sun/Fedora Directory Server uses a special attribute
* passwordexpirationtime. It has precedence over shadow*
* because it actually locks the expired password at the LDAP
* server level. The correct way to check expiration should
* be using LDAP controls, unfortunately PHP doesn't support
* controls on bind() responses. */
$ldaptimepattern = "/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})Z/";
if (preg_match($ldaptimepattern, $info['passwordexpirationtime'][0], $regs)) {
/* Sun/Fedora Directory Server return expiration time, not
* last change time. We emulate the behaviour taking it
* back to maxage. */
$lookupshadow['shadowlastchange'] = floor(mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]) / 86400) - $this->_params['maxage'];
/* Password expiry attributes are in not accessible policy
* entry. */
$lookupshadow['shadowwarning'] = $this->_params['warnage'];
$lookupshadow['shadowmin'] = $this->_params['minage'];
$lookupshadow['shadowmax'] = $this->_params['maxage'];
} elseif ($this->_logger) {
$this->_logger->log('Wrong time format: ' . $info['passwordexpirationtime'][0], 'ERR');
}
} else {
if (isset($info['shadowmax'][0])) {
$lookupshadow['shadowmax'] = $info['shadowmax'][0];
}
if (isset($info['shadowmin'][0])) {
$lookupshadow['shadowmin'] = $info['shadowmin'][0];
}
if (isset($info['shadowlastchange'][0])) {
$lookupshadow['shadowlastchange'] = $info['shadowlastchange'][0];
}
if (isset($info['shadowwarning'][0])) {
$lookupshadow['shadowwarning'] = $info['shadowwarning'][0];
}
}
return $lookupshadow;
}
/**
* Find out if the given set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
if (!strlen($credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
/* Search for the user's full DN. */
$this->_ldap->bind();
try {
$dn = $this->_ldap->findUserDN($userId);
} catch (Horde_Exception_NotFound $e) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
} catch (Horde_Exception_Ldap $e) {
throw new Horde_Auth_Exception($e->getMessage(), Horde_Auth::REASON_MESSAGE);
}
/* Attempt to bind to the LDAP server as the user. */
try {
$this->_ldap->bind($dn, $credentials['password']);
// Be sure we rebind as the configured user.
$this->_ldap->bind();
} catch (Horde_Ldap_Exception $e) {
// Be sure we rebind as the configured user.
$this->_ldap->bind();
if (Horde_Ldap::errorName($e->getCode() == 'LDAP_INVALID_CREDENTIALS')) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
throw new Horde_Auth_Exception($e->getMessage(), Horde_Auth::REASON_MESSAGE);
}
if ($this->_params['password_expiration'] == 'yes') {
$shadow = $this->_lookupShadow($dn);
if ($shadow['shadowmax'] && $shadow['shadowlastchange'] &&
$shadow['shadowwarning']) {
$today = floor(time() / 86400);
$toexpire = $shadow['shadowlastchange'] +
$shadow['shadowmax'] - $today;
$warnday = $shadow['shadowlastchange'] + $shadow['shadowmax'] - $shadow['shadowwarning'];
if ($today >= $warnday) {
$this->setCredential('expire', $toexpire);
}
if ($toexpire == 0) {
$this->setCredential('change', true);
} elseif ($toexpire < 0) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_EXPIRED);
}
}
}
}
/**
* Add a set of authentication credentials.
*
* @param string $userId The userId to add.
* @param array $credentials The credentials to be set.
*
* @throws Horde_Auth_Exception
*/
public function addUser($userId, $credentials)
{
if (!empty($this->_params['ad'])) {
throw new Horde_Auth_Exception(__CLASS__ . ': Adding users is not supported for Active Directory.');
}
if (isset($credentials['ldap'])) {
$entry = $credentials['ldap'];
$dn = $entry['dn'];
/* Remove the dn entry from the array. */
unset($entry['dn']);
} else {
/* Try this simple default and hope it works. */
$dn = $this->_params['uid'] . '=' . $userId . ','
. $this->_params['basedn'];
$entry['cn'] = $userId;
$entry['sn'] = $userId;
$entry[$this->_params['uid']] = $userId;
$entry['objectclass'] = array_merge(
array('top'),
$this->_params['newuser_objectclass']);
$entry['userPassword'] = Horde_Auth::getCryptedPassword(
$credentials['password'], '',
$this->_params['encryption'],
'true');
if ($this->_params['password_expiration'] == 'yes') {
$entry['shadowMin'] = $this->_params['minage'];
$entry['shadowMax'] = $this->_params['maxage'];
$entry['shadowWarning'] = $this->_params['warnage'];
$entry['shadowLastChange'] = floor(time() / 86400);
}
}
try {
$this->_ldap->add(Horde_Ldap_Entry::createFresh($dn, $entry));
} catch (Horde_Ldap_Exception $e) {
throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to add user "%s". This is what the server said: ', $userId) . $e->getMessage());
}
}
/**
* Remove a set of authentication credentials.
*
* @param string $userId The userId to add.
* @param string $dn TODO
*
* @throws Horde_Auth_Exception
*/
public function removeUser($userId, $dn = null)
{
if (!empty($this->_params['ad'])) {
throw new Horde_Auth_Exception(__CLASS__ . ': Removing users is not supported for Active Directory');
}
if (is_null($dn)) {
/* Search for the user's full DN. */
try {
$dn = $this->_ldap->findUserDN($userId);
} catch (Horde_Exception_Ldap $e) {
throw new Horde_Auth_Exception($e);
}
}
try {
$this->_ldap->delete($dn);
} catch (Horde_Ldap_Exception $e) {
throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to remove user "%s"', $userId));
}
}
/**
* Update a set of authentication credentials.
*
* @todo Clean this up for Horde 5.
*
* @param string $oldID The old userId.
* @param string $newID The new userId.
* @param array $credentials The new credentials.
* @param string $olddn The old user DN.
* @param string $newdn The new user DN.
*
* @throws Horde_Auth_Exception
*/
public function updateUser($oldID, $newID, $credentials, $olddn = null,
$newdn = null)
{
if (!empty($this->_params['ad'])) {
throw new Horde_Auth_Exception(__CLASS__ . ': Updating users is not supported for Active Directory.');
}
if (is_null($olddn)) {
/* Search for the user's full DN. */
try {
$dn = $this->_ldap->findUserDN($oldID);
} catch (Horde_Exception_Ldap $e) {
throw new Horde_Auth_Exception($e);
}
$olddn = $dn;
$newdn = preg_replace('/uid=.*?,/', 'uid=' . $newID . ',', $dn, 1);
$shadow = $this->_lookupShadow($dn);
/* If shadowmin hasn't yet expired only change when we are
administrator */
if ($shadow['shadowlastchange'] &&
$shadow['shadowmin'] &&
($shadow['shadowlastchange'] + $shadow['shadowmin'] > (time() / 86400))) {
throw new Horde_Auth_Exception('Minimum password age has not yet expired');
}
/* Set the lastchange field */
if ($shadow['shadowlastchange']) {
$entry['shadowlastchange'] = floor(time() / 86400);
}
/* Encrypt the new password */
$entry['userpassword'] = Horde_Auth::getCryptedPassword(
$credentials['password'], '',
$this->_params['encryption'],
'true');
} else {
$entry = $credentials;
unset($entry['dn']);
}
try {
if ($oldID != $newID) {
$this->_ldap->move($olddn, $newdn);
$this->_ldap->modify($newdn, array('replace' => $entry));
} else {
$this->_ldap->modify($olddn, array('replace' => $entry));
}
} catch (Horde_Ldap_Exception $e) {
throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to update user "%s"', $newID));
}
}
/**
* Reset a user's password. Used for example when the user does not
* remember the existing password.
*
* @param string $userId The user id for which to reset the password.
*
* @return string The new password on success.
* @throws Horde_Auth_Exception
*/
public function resetPassword($userId)
{
if (!empty($this->_params['ad'])) {
throw new Horde_Auth_Exception(__CLASS__ . ': Updating users is not supported for Active Directory.');
}
/* Search for the user's full DN. */
try {
$dn = $this->_ldap->findUserDN($userId);
} catch (Horde_Exception_Ldap $e) {
throw new Horde_Auth_Exception($e);
}
/* Get a new random password. */
$password = Horde_Auth::genRandomPassword();
/* Encrypt the new password */
$entry = array(
'userpassword' => Horde_Auth::getCryptedPassword($password,
'',
$this->_params['encryption'],
'true'));
/* Set the lastchange field */
$shadow = $this->_lookupShadow($dn);
if ($shadow['shadowlastchange']) {
$entry['shadowlastchange'] = floor(time() / 86400);
}
/* Update user entry. */
try {
$this->_ldap->modify($dn, array('replace' => $entry));
} catch (Horde_Ldap_Exception $e) {
throw new Horde_Auth_Exception($e);
}
return $password;
}
/**
* Lists all users in the system.
*
* @param boolean $sort Sort the users?
*
* @return array The array of userIds.
* @throws Horde_Auth_Exception
*/
public function listUsers($sort = false)
{
$params = array(
'attributes' => array($this->_params['uid']),
'scope' => $this->_params['scope'],
'sizelimit' => isset($this->_params['sizelimit']) ? $this->_params['sizelimit'] : 0
);
/* Add a sizelimit, if specified. Default is 0, which means no limit.
* Note: You cannot override a server-side limit with this. */
$userlist = array();
try {
$search = $this->_ldap->search(
$this->_params['basedn'],
Horde_Ldap_Filter::build(array('filter' => $this->_params['filter'])),
$params);
$uid = Horde_String::lower($this->_params['uid']);
foreach ($search as $val) {
$userlist[] = $val->getValue($uid, 'single');
}
} catch (Horde_Ldap_Exception $e) {
}
return $this->_sort($userlist, $sort);
}
/**
* Checks if $userId exists in the LDAP backend system.
*
* @author Marco Ferrante, University of Genova (I)
*
* @param string $userId User ID for which to check
*
* @return boolean Whether or not $userId already exists.
*/
public function exists($userId)
{
$params = array(
'scope' => $this->_params['scope']
);
try {
$uidfilter = Horde_Ldap_Filter::create($this->_params['uid'], 'equals', $userId);
$classfilter = Horde_Ldap_Filter::build(array('filter' => $this->_params['filter']));
$search = $this->_ldap->search(
$this->_params['basedn'],
Horde_Ldap_Filter::combine('and', array($uidfilter, $classfilter)),
$params);
if ($search->count() < 1) {
return false;
}
if ($search->count() > 1 && $this->_logger) {
$this->_logger->log('Multiple LDAP entries with user identifier ' . $userId, 'WARN');
}
return true;
} catch (Horde_Ldap_Exception $e) {
if ($this->_logger) {
$this->_logger->log('Error searching LDAP user: ' . $e->getMessage(), 'ERR');
}
return false;
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Login.php 0000664 0001750 0001750 00000004532 12653661601 016225 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Login extends Horde_Auth_Base
{
/**
* List of users that should be excluded from being listed/handled
* in any way by this driver.
*
* @var array
*/
protected $_exclude = array(
'root', 'daemon', 'bin', 'sys', 'sync', 'games', 'man', 'lp', 'mail',
'news', 'uucp', 'proxy', 'postgres', 'www-data', 'backup', 'operator',
'list', 'irc', 'gnats', 'nobody', 'identd', 'sshd', 'gdm', 'postfix',
'mysql', 'cyrus', 'ftp'
);
/**
* Constructs a new Login authentication object.
*
* @param array $params Optional parameters:
*
* 'location' - (string) Location of the su binary.
* DEFAULT: /bin/su
*
*/
public function __construct(array $params = array())
{
if (empty($params['location'])) {
$params['location'] = '/bin/su';
}
parent::__construct($params);
}
/**
* Find out if a set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials.
*
* @return boolean Whether or not the credentials are valid.
*/
protected function _authenticate($userId, $credentials)
{
if (empty($credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
$proc = @popen($this->_location . ' -c /bin/true ' . $userId, 'w');
if (!is_resource($proc)) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_FAILED);
}
fwrite($proc, $credentials['password']);
if (@pclose($proc) !== 0) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_FAILED);
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Msad.php 0000664 0001750 0001750 00000022760 12653661601 016044 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Msad class provides an experimental MSAD extension of the
* LDAP implementation of the Horde authentication system.
*
* @todo Use Horde_Ldap
*
* @author Francois Helly
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Msad extends Horde_Auth_Ldap
{
/**
* Constructor.
*
* @param array $params A hash containing connection parameters.
*
* @throws Horde_Auth_Exception
*/
public function __construct($params = array())
{
$params = array_merge(array(
'adduser' => true,
'authId' => 'initials',
'encryption' => 'msad',
'newuser_objectclass' => 'user',
'password_expiration' => 'no',
'port' => 389,
'ssl' => false,
'uid' => array('samaccountname')
), $params);
if (!is_array($params['uid'])) {
$params['uid'] = array($params['uid']);
}
/* Ensure we've been provided with all of the necessary parameters. */
//Horde::assertDriverConfig($params, 'auth',
// array('hostspec', 'basedn'), 'authentication MSAD');
/* Adjust capabilities: depending on if SSL encryption is
* enabled or not */
$this->_capabilities = array(
'add' => ($params['ssl'] || $params['adduser']),
'list' => true,
'remove' => true,
'resetpassword' => $params['ssl'],
'update' => $params['ssl']
);
parent::__construct($params);
}
/**
* Add a set of authentication credentials.
*
* @param string $accountName The user sAMAccountName to find.
* @param array $credentials The credentials to be set.
*
* @throws Horde_Auth_Exception
*/
public function addUser($accountName, $credentials)
{
/* Connect to the MSAD server. */
$this->_connect();
if (isset($credentials['ldap'])) {
$dn = $credentials['ldap']['dn'];
} else {
$basedn = isset($credentials['basedn'])
? $credentials['basedn']
: $this->_params['basedn'];
/* Set a default CN */
$dn = 'cn=' . $accountName . ',' . $basedn;
$entry['cn'] = $accountName;
$entry['samaccountname'] = $accountName;
$entry['objectclass'][0] = "top";
$entry['objectclass'][1] = "person";
$entry['objectclass'][2] = "organizationalPerson";
$entry['objectclass'][3] = "user";
$entry['description'] = (isset($credentials['description'])) ?
$credentials['description'] : 'New horde user';
if ($this->_params['ssl']) {
$entry["AccountDisabled"] = false;
}
$entry['userPassword'] = Horde_Auth::getCryptedPassword($credentials['password'],'',
$this->_params['encryption'],
false);
if (isset($this->_params['binddn'])) {
$entry['manager'] = $this->_params['binddn'];
}
}
$success = @ldap_add($this->_ds, $dn, $entry);
if (!$success) {
throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to add user "%s". This is what the server said: ', $accountName) . ldap_error($this->_ds));
}
@ldap_close($this->_ds);
}
/**
* Remove a set of authentication credentials.
*
* @param string $accountName The user sAMAccountName to remove.
* @param string $dn TODO
*
* @throws Horde_Auth_Exception
*/
public function removeUser($accountName, $dn = null)
{
/* Connect to the MSAD server. */
$this->_connect();
if (is_null($dn)) {
/* Search for the user's full DN. */
$dn = $this->_findDN($accountName);
}
if (!@ldap_delete($this->_ds, $dn)) {
throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to remove user "%s"', $accountName));
}
@ldap_close($this->_ds);
}
/**
* Update a set of authentication credentials.
*
* @param string $oldId The old userId.
* @param string $newId The new userId.
* @param array $credentials The new credentials.
* @param string $olddn The old user DN.
* @param string $newdn The new user DN.
*
* @throws Horde_Auth_Exception
*/
public function updateUser($oldId, $newId, $credentials, $olddn = null,
$newdn = null)
{
/* Connect to the MSAD server. */
$this->_connect();
if (isset($credentials['ldap'])) {
$olddn = $credentials['ldap']['dn'];
} else {
/* Search for the user's full DN. */
$dn = $this->_findDN($oldId);
/* Encrypt the new password */
if (isset($credentials['password'])) {
$entry['userpassword'] = Horde_Auth::getCryptedPassword($credentials['password'],'',
$this->_params['encryption'],
true);
}
}
if ($oldId != $newID) {
$newdn = str_replace($oldId, $newID, $dn);
ldap_rename($this->_ds, $olddn, $newdn, $this->_params['basedn'], true);
$success = @ldap_modify($this->_ds, $newdn, $entry);
} else {
$success = @ldap_modify($this->_ds, $olddn, $entry);
}
if (!$success) {
throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to update user "%s"', $newID));
}
@ldap_close($this->_ds);
}
/**
* Reset a user's password. Used for example when the user does not
* remember the existing password.
*
* @param string $user_id The user id for which to reset the password.
*
* @return string The new password on success.
* @throws Horde_Auth_Exception
*/
public function resetPassword($user_id)
{
/* Get a new random password. */
$password = Horde_Auth::genRandomPassword() . '/';
$this->updateUser($user_id, $user_id, array('userPassword' => $password));
return $password;
}
/**
* Does an ldap connect and binds as the guest user.
*
* @throws Horde_Auth_Exception
*/
protected function _connect()
{
/* Connect to the MSAD server. */
$ssl = ($this->_params['ssl']) ? 'ldaps://' : '';
$this->_ds = ldap_connect($ssl . $this->_params['hostspec'], $this->_params['port']);
if (!$this->_ds) {
throw new Horde_Auth_Exception('Failed to connect to MSAD server.');
}
if ($this->_logger) {
if (!ldap_set_option($this->_ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
$this->_logger->log(sprintf('Set MSAD protocol version to %d failed: [%d] %s', 3, ldap_errno($conn), ldap_error($conn)));
}
if (!ldap_set_option($this->_ds, LDAP_OPT_REFERRALS, 0)) {
$this->_logger->log(sprintf('Set MSAD referrals option to %d failed: [%d] %s', 0, ldap_errno($conn), ldap_error($conn)));
}
}
if (isset($this->_params['binddn'])) {
$bind = ldap_bind($this->_ds,
$this->_params['binddn'],
$this->_params['password']);
} else {
$bind = ldap_bind($this->_ds);
}
if (!$bind) {
throw new Horde_Auth_Exception('Could not bind to MSAD server.');
}
}
/**
* Find the user dn
*
* @param string $userId The user UID to find.
*
* @return string The user's full DN
*/
protected function _findDN($userId)
{
/* Search for the user's full DN. */
foreach ($this->_params['uid'] as $uid) {
$entries = array($uid);
if ($uid != $this->_params['authId']) {
$entries[] = $this->_params['authId'];
}
$search = @ldap_search($this->_ds, $this->_params['basedn'],
$uid . '=' . $userId,
$entries
);
/* Searching the tree is not successful */
if (!$search) {
throw new Horde_Auth_Exception('Could not search the MSAD server.');
}
/* Fetch the search result */
$result = @ldap_get_entries($this->_ds, $search);
/* The result isn't empty: the DN was found */
if (is_array($result) && (count($result) > 1)) {
break;
}
}
if (!is_array($result) || (count($result) <= 1)) {
throw new Horde_Auth_Exception('Empty result.');
}
/* Be sure the horde userId is the configured one */
$this->_credentials['userId'] = $result[0][$this->_params['authId']][0];
return $result[0]['dn'];
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Pam.php 0000664 0001750 0001750 00000004226 12653661601 015672 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Pam:: class provides a PAM-based implementation of the Horde
* authentication system.
*
* PAM (Pluggable Authentication Modules) is a flexible mechanism for
* authenticating users. It has become the standard authentication system for
* Linux, Solaris and FreeBSD.
*
* This driver relies on the PECL PAM package:
*
* http://pecl.php.net/package/PAM
*
* @author Jon Parise
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Pam extends Horde_Auth_Base
{
/**
* Constructor.
*
* @param array $params Optional parameters:
*
* 'service' - (string) The name of the PAM service to use when
* authenticating.
* DEFAULT: php
*
*
* @throws Horde_Auth_Exception
*/
public function __construct(array $params = array())
{
if (!Horde_Util::extensionExists('pam')) {
throw new Horde_Auth_Exception('PAM authentication is not available.');
}
if (!empty($params['service'])) {
ini_set('pam.servicename', $params['service']);
}
parent::__construct($params);
}
/**
* Find out if a set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
if (empty($credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
$error = null;
if (!pam_auth($userId, $credentials['password'], $error)) {
throw new Horde_Auth_Exception($error);
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Passwd.php 0000664 0001750 0001750 00000031514 12653661601 016416 0 ustar jan jan
* Copyright 2002-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you did
* not receive this file, http://www.horde.org/licenses/lgpl21
*
* @author Rasmus Lerdorf
* @author Chuck Hagenbuch
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Passwd class provides a passwd-file implementation of the
* Horde authentication system.
*
* @author Rasmus Lerdorf
* @author Chuck Hagenbuch
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Passwd extends Horde_Auth_Base
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'list' => true,
'authenticate' => true,
);
/**
* Hash list of users.
*
* @var array
*/
protected $_users = null;
/**
* Array of groups and members.
*
* @var array
*/
protected $_groups = array();
/**
* Filehandle for lockfile.
*
* @var resource
*/
protected $_fplock;
/**
* Locking state.
*
* @var boolean
*/
protected $_locked;
/**
* List of users that should be excluded from being listed/handled
* in any way by this driver.
*
* @var array
*/
protected $_exclude = array(
'root', 'daemon', 'bin', 'sys', 'sync', 'games', 'man', 'lp', 'mail',
'news', 'uucp', 'proxy', 'postgres', 'www-data', 'backup', 'operator',
'list', 'irc', 'gnats', 'nobody', 'identd', 'sshd', 'gdm', 'postfix',
'mysql', 'cyrus', 'ftp',
);
/**
* Constructor.
*
* @param array $params Connection parameters:
*
* 'encryption' - (string) The encryption to use to store the password in
* the table (e.g. plain, crypt, md5-hex, md5-base64, smd5,
* sha, ssha, aprmd5).
* DEFAULT: 'crypt-des'
* 'filename' - (string) [REQUIRED] The passwd file to use.
* 'lock' - (boolean) Should we lock the passwd file? The password file
* cannot be changed (add, edit, or delete users) unless this is
* true.
* DEFAULT: false
* 'show_encryption' - (boolean) Whether or not to prepend the encryption
* in the password field.
* DEFAULT: false
*
*
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
if (!isset($params['filename'])) {
throw new InvalidArgumentException('Missing filename parameter.');
}
$params = array_merge(array(
'encryption' => 'crypt-des',
'lock' => false,
'show_encryption' => false
), $params);
parent::__construct($params);
}
/**
* Writes changes to passwd file and unlocks it. Takes no arguments and
* has no return value. Called on script shutdown.
*/
public function __destruct()
{
if ($this->_locked) {
foreach ($this->_users as $user => $pass) {
$data = $user . ':' . $pass;
if ($this->_users[$user]) {
$data .= ':' . $this->_users[$user];
}
fputs($this->_fplock, $data . "\n");
}
rename($this->_lockfile, $this->_params['filename']);
flock($this->_fplock, LOCK_UN);
$this->_locked = false;
fclose($this->_fplock);
}
}
/**
* Queries the current Auth object to find out if it supports the given
* capability.
*
* @param string $capability The capability to test for.
*
* @return boolean Whether or not the capability is supported.
*/
public function hasCapability($capability)
{
if ($this->_params['lock']) {
switch ($capability) {
case 'add':
case 'update':
case 'resetpassword':
case 'remove':
return true;
}
}
return parent::hasCapability($capability);
}
/**
* Read and, if requested, lock the password file.
*
* @throws Horde_Auth_Exception
*/
protected function _read()
{
if (is_array($this->_users)) {
return;
}
if (empty($this->_params['filename'])) {
throw new Horde_Auth_Exception('No password file set.');
}
if ($this->_params['lock']) {
$this->_fplock = fopen(sys_get_temp_dir() . '/passwd.lock', 'w');
flock($this->_fplock, LOCK_EX);
$this->_locked = true;
}
$fp = fopen($this->_params['filename'], 'r');
if (!$fp) {
throw new Horde_Auth_Exception("Couldn't open '" . $this->_params['filename'] . "'.");
}
$this->_users = array();
while (!feof($fp)) {
$line = trim(fgets($fp, 256));
if (empty($line)) {
continue;
}
$parts = explode(':', $line);
if (!count($parts)) {
continue;
}
$user = $parts[0];
$userinfo = array();
if (strlen($user) && !in_array($user, $this->_exclude)) {
if (isset($parts[1])) {
$userinfo['password'] = $parts[1];
}
if (isset($parts[2])) {
$userinfo['uid'] = $parts[2];
}
if (isset($parts[3])) {
$userinfo['gid'] = $parts[3];
}
if (isset($parts[4])) {
$userinfo['info'] = $parts[4];
}
if (isset($parts[5])) {
$userinfo['home'] = $parts[5];
}
if (isset($parts[6])) {
$userinfo['shell'] = $parts[6];
}
$this->_users[$user] = $userinfo;
}
}
fclose($fp);
if (!empty($this->_params['group_filename'])) {
$fp = fopen($this->_params['group_filename'], 'r');
if (!$fp) {
throw new Horde_Auth_Exception("Couldn't open '" . $this->_params['group_filename'] . "'.");
}
$this->_groups = array();
while (!feof($fp)) {
$line = trim(fgets($fp));
if (empty($line)) {
continue;
}
$parts = explode(':', $line);
$group = array_shift($parts);
$users = array_pop($parts);
$this->_groups[$group] = array_flip(preg_split('/\s*[,\s]\s*/', trim($users), -1, PREG_SPLIT_NO_EMPTY));
}
fclose($fp);
}
}
/**
* Find out if a set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
if (empty($credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
try {
$this->_read();
} catch (Horde_Auth_Exception $e) {
if ($this->_logger) {
$this->_logger->log($e, 'ERR');
}
throw new Horde_Auth_Exception('', Horde_Auth::REASON_FAILED);
}
if (!isset($this->_users[$userId]) ||
!$this->_comparePasswords($this->_users[$userId]['password'], $credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
if (!empty($this->_params['required_groups'])) {
$allowed = false;
foreach ($this->_params['required_groups'] as $group) {
if (isset($this->_groups[$group][$userId])) {
$allowed = true;
break;
}
}
if (!$allowed) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
}
}
/**
* Lists all users in the system.
*
* @param boolean $sort Sort the users?
*
* @return array The array of userIds.
* @throws Horde_Auth_Exception
*/
public function listUsers($sort = false)
{
$this->_read();
$users = array_keys($this->_users);
if (empty($this->_params['required_groups'])) {
return $this->_sort($users, $sort);
}
$groupUsers = array();
foreach ($this->_params['required_groups'] as $group) {
$groupUsers = array_merge($groupUsers, array_intersect($users, array_keys($this->_groups[$group])));
}
return $this->_sort($groupUsers, $sort);
}
/**
* Add a set of authentication credentials.
*
* @param string $userId The userId to add.
* @param array $credentials The credentials to add.
*
* @throws Horde_Auth_Exception
*/
public function addUser($userId, $credentials)
{
$this->_read();
if (!$this->_locked) {
throw new Horde_Auth_Exception('Password file not locked');
}
if (isset($this->_users[$userId])) {
throw new Horde_Auth_Exception("Couldn't add user '$userId', because the user already exists.");
}
$this->_users[$userId] = array(
'password' => Horde_Auth::getCryptedPassword($credentials['password'],
'',
$this->_params['encryption'],
$this->_params['show_encryption']),
);
}
/**
* Update a set of authentication credentials.
*
* @param string $oldID The old userId.
* @param string $newID The new userId.
* @param array $credentials The new credentials
*
* @throws Horde_Auth_Exception
*/
public function updateUser($oldID, $newID, $credentials)
{
$this->_read();
if (!$this->_locked) {
throw new Horde_Auth_Exception('Password file not locked');
}
if (!isset($this->_users[$oldID])) {
throw new Horde_Auth_Exception("Couldn't modify user '$oldID', because the user doesn't exist.");
}
$this->_users[$newID] = array(
'password' => Horde_Auth::getCryptedPassword($credentials['password'],
'',
$this->_params['encryption'],
$this->_params['show_encryption']),
);
return true;
}
/**
* Reset a user's password. Used for example when the user does not
* remember the existing password.
*
* @param string $userId The user id for which to reset the password.
*
* @return string The new password.
* @throws Horde_Auth_Exception
*/
public function resetPassword($userId)
{
/* Get a new random password. */
$password = Horde_Auth::genRandomPassword();
$this->updateUser($userId, $userId, array('password' => $password));
return $password;
}
/**
* Delete a set of authentication credentials.
*
* @param string $userId The userId to delete.
*
* @throws Horde_Auth_Exception
*/
public function removeUser($userId)
{
$this->_read();
if (!$this->_locked) {
throw new Horde_Auth_Exception('Password file not locked');
}
if (!isset($this->_users[$userId])) {
throw new Horde_Auth_Exception("Couldn't delete user '$userId', because the user doesn't exist.");
}
unset($this->_users[$userId]);
}
/**
* Compare an encrypted password to a plaintext string to see if
* they match.
*
* @param string $encrypted The crypted password to compare against.
* @param string $plaintext The plaintext password to verify.
*
* @return boolean True if matched, false otherwise.
*/
protected function _comparePasswords($encrypted, $plaintext)
{
return $encrypted == Horde_Auth::getCryptedPassword($plaintext,
$encrypted,
$this->_params['encryption'],
$this->_params['show_encryption']);
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Peclsasl.php 0000664 0001750 0001750 00000005032 12653661601 016717 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Peclsasl:: class provides a SASL-based implementation of the
* Horde authentication system.
*
* SASL is the Simple Authentication and Security Layer (as defined by RFC
* 2222). It provides a system for adding plugable authenticating support to
* connection-based protocols.
*
* This driver relies on the PECL sasl package:
* http://pecl.php.net/package/sasl
*
* @author Jon Parise
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Peclsasl extends Horde_Auth_Base
{
/**
* Constructor.
*
* @param array $params Optional parameters:
*
* 'app' - (string) The name of the authenticating application.
* DEFAULT: horde
* 'service' - (string) The name of the SASL service to use when
* authenticating.
* DEFAULT: php
*
*
* @throws Horde_Auth_Exception
*/
public function __construct(array $params = array())
{
if (!Horde_Util::extensionExists('sasl')) {
throw new Horde_Auth_Exception('Horde_Auth_Peclsasl:: requires the sasl PECL extension to be loaded.');
}
$params = array_merge(array(
'app' => 'horde',
'service' => 'php'
), $params);
parent::__construct($params);
sasl_server_init($this->_params['app']);
}
/**
* Find out if a set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
if (empty($credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
$conn = sasl_server_new($this->_params['service']);
if (!is_resource($conn)) {
throw new Horde_Auth_Exception('Failed to create new SASL connection.');
}
if (!sasl_checkpass($conn, $userId, $credentials['password'])) {
throw new Horde_Auth_Exception(sasl_errdetail($conn));
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Radius.php 0000664 0001750 0001750 00000011374 12653661601 016406 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Radius class provides a RADIUS implementation of the Horde
* authentication system.
*
* This class requires the 'radius' PECL extension:
* http://pecl.php.net/package/radius
*
* @author Michael Slusarz
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Radius extends Horde_Auth_Base
{
/**
* Constructor.
*
* @param array $params Connection parameters.
*
* 'host' - (string) [REQUIRED] The RADIUS host to use (IP address or
* fully qualified hostname).
* 'method' - (string) [REQUIRED] The RADIUS method to use for validating
* the request.
* Either: 'PAP', 'CHAP_MD5', 'MSCHAPv1', or 'MSCHAPv2'.
* ** CURRENTLY, only 'PAP' is supported. **
* 'nas' - (string) The RADIUS NAS identifier to use.
* DEFAULT: The value of $_SERVER['HTTP_HOST'] or, if not
* defined, then 'localhost'.
* 'port' - (integer) The port to use on the RADIUS server.
* DEFAULT: Whatever the local system identifies as the
* 'radius' UDP port
* 'retries' - (integer) The maximum number of repeated requests to make
* before giving up.
* DEFAULT: 3
* 'secret' - (string) [REQUIRED] The RADIUS shared secret string for the
* host. The RADIUS protocol ignores all but the leading 128
* bytes of the shared secret.
* 'suffix' - (string) The domain name to add to unqualified user names.
* DEFAULT: NONE
* 'timeout' - (integer) The timeout for receiving replies from the server
* (in seconds).
* DEFAULT: 3
*
*
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
if (!Horde_Util::extensionExists('radius')) {
throw new Horde_Auth_Exception(__CLASS__ . ': requires the radius PECL extension to be loaded.');
}
foreach (array('host', 'secret', 'method') as $val) {
if (!isset($params[$val])) {
throw new InvalidArgumentException('Missing ' . $val . ' parameter.');
}
}
$params = array_merge(array(
'nas' => (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost'),
'port' => 0,
'retries' => 3,
'suffix' => '',
'timeout' => 3
), $params);
parent::__construct($params);
}
/**
* Find out if a set of login credentials are valid.
*
* @param string $username The userId to check.
* @param array $credentials An array of login credentials.
* For radius, this must contain a password
* entry.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($username, $credentials)
{
/* Password is required. */
if (!isset($credentials['password'])) {
throw new Horde_Auth_Exception('Password required for RADIUS authentication.');
}
$res = radius_auth_open();
radius_add_server($res, $this->_params['host'], $this->_params['port'], $this->_params['secret'], $this->_params['timeout'], $this->_params['retries']);
radius_create_request($res, RADIUS_ACCESS_REQUEST);
radius_put_attr($res, RADIUS_NAS_IDENTIFIER, $this->_params['nas']);
radius_put_attr($res, RADIUS_NAS_PORT_TYPE, RADIUS_VIRTUAL);
radius_put_attr($res, RADIUS_SERVICE_TYPE, RADIUS_FRAMED);
radius_put_attr($res, RADIUS_FRAMED_PROTOCOL, RADIUS_PPP);
radius_put_attr($res, RADIUS_CALLING_STATION_ID, isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : '127.0.0.1');
/* Insert username/password into request. */
radius_put_attr($res, RADIUS_USER_NAME, $username);
radius_put_attr($res, RADIUS_USER_PASSWORD, $credentials['password']);
/* Send request. */
$success = radius_send_request($res);
switch ($success) {
case RADIUS_ACCESS_ACCEPT:
break;
case RADIUS_ACCESS_REJECT:
throw new Horde_Auth_Exception('Authentication rejected by RADIUS server.');
default:
throw new Horde_Auth_Exception(radius_strerror($res));
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Shibboleth.php 0000664 0001750 0001750 00000007575 12653661601 017252 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Shibboleth class only provides transparent authentication
* based on the headers set by a Shibboleth SP. Note that this class does
* not provide any actual SP functionality, it just takes the username
* from the HTTP headers that should be set by the Shibboleth SP.
*
* @author Cassio Nishiguchi
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Shibboleth extends Horde_Auth_Base
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'transparent' => true
);
/**
* Constructor.
*
* @param array $params Parameters:
*
* 'password_header' - (string) Name of the header holding the password of
* the logged in user.
* 'password_holder' - (string) Where the hordeauth password is stored.
* 'password_preference' - (string) Name of the Horde preference holding
* the password of the logged in user.
* 'username_header' - (string) [REQUIRED] Name of the header holding the
* username of the logged in user.
*
*
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
if (!isset($params['username_header'])) {
throw new InvalidArgumentException('Missing username_header parameter.');
}
$params = array_merge(array(
'password_header' => '',
'password_holder' => '',
'password_preference' => ''
), $params);
parent::__construct($params);
}
/**
* Not implemented.
*
* @param string $userId The userID to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
throw new Horde_Auth_Exception('Unsupported.');
}
/**
* Automatic authentication: checks if the username is set in the
* configured header.
*
* @return boolean Whether or not the client is allowed.
*/
public function transparent()
{
if (empty($_SERVER[$this->_params['username_header']])) {
return false;
}
$username = $_SERVER[$this->_params['username_header']];
// Remove scope from username, if present.
$this->setCredential('userId', $this->_removeScope($username));
// Set password for hordeauth login.
switch ($this->_params['password_holder']) {
case 'header':
$this->setCredential('credentials', array(
'password' => $_SERVER[$this->_params['password_header']]
));
break;
case 'preferences':
$this->setCredential('credentials', array(
'password' => $_SERVER[$this->_params['password_preference']]
));
break;
}
return true;
}
/**
* Removes the scope from the user name, if present.
*
* @param string $username The full user name.
*
* @return string The user name without scope.
*/
protected function _removeScope($username)
{
$pos = strrpos($username, '@');
return ($pos !== false)
? substr($username, 0, $pos)
: $username;
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Smb.php 0000664 0001750 0001750 00000006337 12653661601 015703 0 ustar jan jan
* @author Marcus I. Ryan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
* @todo Add driver for other smbclient extensions https://github.com/eduardok/libsmbclient-php http://pecl.php.net/package/smbclient
*/
/**
* The Horde_Auth_Smb class provides a SMB implementation of the Horde
* authentication system.
*
* This module requires the smbauth extension for PHP:
* http://tekrat.com/wp/smbauth/
*
* At the time of this writing, the extension, and thus this module, only
* supported authentication against a domain, and pdc and bdc must be non-null
* and not equal to each other. In other words, to use this module you must
* have a domain with at least one PDC and one BDC.
*
* @author Jon Parise
* @author Marcus I. Ryan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Smb extends Horde_Auth_Base
{
/**
* Constructor.
*
* @param array $params Parameters:
*
* 'domain' - (string) [REQUIRED] The domain name to authenticate with.
* 'group' - Group name that the user must be a member of.
* DEFAULT: none
* 'hostspec' - (string) [REQUIRED] IP, DNS Name, or NetBios name of the
* SMB server to authenticate with.
*
*
* @throws Horde_Auth_Exception
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
if (!Horde_Util::extensionExists('smbauth')) {
throw new Horde_Auth_Exception(__CLASS__ . ': Required smbauth extension not found.');
}
foreach (array('domain', 'hostspec') as $val) {
if (empty($params[$val])) {
throw new InvalidArgumentException('Missing ' . $val . ' parameter.');
}
}
$params = array_merge(array(
'group' => null
), $params);
parent::__construct($params);
}
/**
* Find out if the given set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
public function _authenticate($userId, $credentials)
{
if (empty($credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
/* Authenticate. */
$rval = validate($this->_params['hostspec'],
$this->_params['domain'],
empty($this->_params['group']) ? '' : $this->_params['group'],
$userId,
$credentials['password']);
if ($rval === 1) {
throw new Horde_Auth_Exception('Failed to connect to SMB server.');
} elseif ($rval !== 0) {
throw new Horde_Auth_Exception(err2str());
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Smbclient.php 0000664 0001750 0001750 00000005447 12653661601 017103 0 ustar jan jan
* @author Marcus I. Ryan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
* @todo Add driver for smbclient extension https://github.com/eduardok/libsmbclient-php
*/
/**
* The Horde_Auth_Smbclient class provides an smbclient implementation of
* the Horde authentication system.
*
* @author Jon Parise
* @author Marcus I. Ryan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Smbclient extends Horde_Auth_Base
{
/**
* Constructor.
*
* @param array $params Parameters:
*
* 'domain' - (string) [REQUIRED] The domain name to authenticate with.
* 'group' - Group name that the user must be a member of.
* DEFAULT: none
* 'hostspec' - (string) [REQUIRED] IP, DNS Name, or NetBios name of the
* SMB server to authenticate with.
* 'smbclient_path' - (string) [REQUIRED] The location of the smbclient
* utility.
*
*
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
foreach (array('hostspec', 'domain', 'smbclient_path') as $val) {
if (empty($params[$val])) {
throw new InvalidArgumentException('Missing ' . $val . ' parameter.');
}
}
parent::__construct($params);
}
/**
* Find out if the given set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
if (empty($credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
/* Authenticate. */
$cmdline = implode(' ', array(
$this->_params['smbclient_path'],
'-L',
$this->_params['hostspec'],
'-W',
$this->_params['domain'],
'-U',
$userId
));
$sc = popen($cmdline, 'w');
if ($sc === false) {
throw new Horde_Auth_Exception('Unable to execute smbclient.');
}
fwrite($sc, $credentials['password']);
$rc = pclose($sc);
if (intval($rc & 0xff) != 0) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Sql.php 0000664 0001750 0001750 00000033200 12653661601 015706 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth_Sql class provides a SQL implementation of the Horde
* authentication system.
*
* The table structure for the Auth system needs to be created with the shipped
* migration scripts. See "horde-db-migrate-component --help" for details.
*
* @author Chuck Hagenbuch
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Sql extends Horde_Auth_Base
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'add' => true,
'list' => true,
'remove' => true,
'resetpassword' => true,
'update' => true,
'authenticate' => true,
);
/**
* Handle for the current database connection.
*
* @var Horde_Db_Adapter
*/
protected $_db;
/**
* Constructor
*
* @param array $params Parameters:
* 'db' - (Horde_Db_Adapter) [REQUIRED] Database object.
*
* 'encryption' - (string) The encryption to use to store the password in
* the table (e.g. plain, crypt, md5-hex, md5-base64, smd5,
* sha, ssha, aprmd5).
* DEFAULT: 'md5-hex'
* 'hard_expiration_field' - (string) The name of the field containing a
* date after which the account is no longer
* valid and the user will not be able to log in
* at all.
* DEFAULT: none
* 'password_field' - (string) The name of the password field in the auth
* table.
* DEFAULT: 'user_pass'
* 'show_encryption' - (boolean) Whether or not to prepend the encryption
* in the password field.
* DEFAULT: false
* 'soft_expiration_field' - (string) The name of the field containing a
* date after which the system will request the
* user change his or her password.
* DEFAULT: none
* 'table' - (string) The name of the SQL table to use in 'database'.
* DEFAULT: 'horde_users'
* 'username_field' - (string) The name of the username field in the auth
* table.
* DEFAULT: 'user_uid'
*
*
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
if (!isset($params['db'])) {
throw new InvalidArgumentException('Missing db parameter.');
}
$this->_db = $params['db'];
unset($params['db']);
$params = array_merge(array(
'encryption' => 'md5-hex',
'password_field' => 'user_pass',
'show_encryption' => false,
'table' => 'horde_users',
'username_field' => 'user_uid',
'soft_expiration_field' => null,
'soft_expiration_window' => null,
'hard_expiration_field' => null,
'hard_expiration_window' => null
), $params);
parent::__construct($params);
/* Only allow limits when there is a storage configured */
if ((empty($params['soft_expiration_field'])) &&
($params['soft_expiration_window'] > 0)) {
throw new InvalidArgumentException('You cannot set [soft_expiration_window] without [soft_expiration_field].');
}
if (($params['hard_expiration_field'] == '') &&
($params['hard_expiration_window'] > 0)) {
throw new InvalidArgumentException('You cannot set [hard_expiration_window] without [hard_expiration_field].');
}
}
/**
* Find out if a set of login credentials are valid.
*
* @param string $userId The userId to check.
* @param array $credentials The credentials to use.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
/* Build the SQL query. */
$query = sprintf('SELECT * FROM %s WHERE %s = ?',
$this->_params['table'],
$this->_params['username_field']);
$values = array($userId);
try {
$row = $this->_db->selectOne($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_FAILED);
}
if (!$row ||
!$this->_comparePasswords($row[$this->_params['password_field']], $credentials['password'])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
}
$now = time();
if (!empty($this->_params['hard_expiration_field']) &&
!empty($row[$this->_params['hard_expiration_field']]) &&
($now > $row[$this->_params['hard_expiration_field']])) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_EXPIRED);
}
if (!empty($this->_params['soft_expiration_field']) &&
!empty($row[$this->_params['soft_expiration_field']]) &&
($now > $row[$this->_params['soft_expiration_field']])) {
$this->setCredential('change', true);
$this->setCredential('expire', $now);
}
}
/**
* Add a set of authentication credentials.
*
* @param string $userId The userId to add.
* @param array $credentials The credentials to add.
*
* @throws Horde_Auth_Exception
*/
public function addUser($userId, $credentials)
{
/* Build the SQL query. */
$query = sprintf('INSERT INTO %s (%s, %s',
$this->_params['table'],
$this->_params['username_field'],
$this->_params['password_field']);
$query_values_part = ' VALUES (?, ?';
$values = array($userId,
Horde_Auth::getCryptedPassword($credentials['password'],
'',
$this->_params['encryption'],
$this->_params['show_encryption']));
if (!empty($this->_params['soft_expiration_field'])) {
$query .= sprintf(', %s', $this->_params['soft_expiration_field']);
$query_values_part .= ', ?';
$values[] = $this->_calc_expiration('soft');
}
if (!empty($this->_params['hard_expiration_field'])) {
$query .= sprintf(', %s', $this->_params['hard_expiration_field']);
$query_values_part .= ', ?';
$values[] = $this->_calc_expiration('hard');
}
$query .= ')' . $query_values_part . ')';
try {
$this->_db->insert($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception($e);
}
}
/**
* Update a set of authentication credentials.
*
* @param string $oldID The old userId.
* @param string $newID The new userId.
* @param array $credentials The new credentials
*
* @throws Horde_Auth_Exception
*/
public function updateUser($oldID, $newID, $credentials)
{
$query = sprintf('UPDATE %s SET ', $this->_params['table']);
$values = array();
/* Build the SQL query. */
$query .= $this->_params['username_field'] . ' = ?';
$values[] = $newID;
$query .= ', ' . $this->_params['password_field'] . ' = ?';
$values[] = Horde_Auth::getCryptedPassword($credentials['password'], '', $this->_params['encryption'], $this->_params['show_encryption']);
if (!empty($this->_params['soft_expiration_field'])) {
$query .= ', ' . $this->_params['soft_expiration_field'] . ' = ?';
$values[] = $this->_calc_expiration('soft');
}
if (!empty($this->_params['hard_expiration_field'])) {
$query .= ', ' . $this->_params['hard_expiration_field'] . ' = ?';
$values[] = $this->_calc_expiration('hard');
}
$query .= sprintf(' WHERE %s = ?', $this->_params['username_field']);
$values[] = $oldID;
try {
$this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception($e);
}
}
/**
* Reset a user's password. Used for example when the user does not
* remember the existing password.
*
* @param string $userId The user id for which to reset the password.
*
* @return string The new password on success.
* @throws Horde_Auth_Exception
*/
public function resetPassword($userId)
{
/* Get a new random password. */
$password = Horde_Auth::genRandomPassword();
/* Build the SQL query. */
$query = sprintf('UPDATE %s SET %s = ?',
$this->_params['table'],
$this->_params['password_field']);
$values = array(Horde_Auth::getCryptedPassword($password,
'',
$this->_params['encryption'],
$this->_params['show_encryption']));
if (!empty($this->_params['soft_expiration_field'])) {
$query .= ', ' . $this->_params['soft_expiration_field'] . ' = ?';
$values[] = $this->_calc_expiration('soft');
}
if (!empty($this->_params['hard_expiration_field'])) {
$query .= ', ' . $this->_params['hard_expiration_field'] . ' = ?';
$values[] = $this->_calc_expiration('hard');
}
$query .= sprintf(' WHERE %s = ?', $this->_params['username_field']);
$values[] = $userId;
try {
$this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception($e);
}
return $password;
}
/**
* Delete a set of authentication credentials.
*
* @param string $userId The userId to delete.
*
* @throws Horde_Auth_Exception
*/
public function removeUser($userId)
{
/* Build the SQL query. */
$query = sprintf('DELETE FROM %s WHERE %s = ?',
$this->_params['table'],
$this->_params['username_field']);
$values = array($userId);
try {
$this->_db->delete($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception($e);
}
}
/**
* List all users in the system.
*
* @param boolean $sort Sort the users?
*
* @return array The array of userIds.
* @throws Horde_Auth_Exception
*/
public function listUsers($sort = false)
{
/* Build the SQL query. */
$query = sprintf('SELECT %s FROM %s',
$this->_params['username_field'],
$this->_params['table']);
if ($sort) {
$query .= sprintf(' ORDER BY %s ASC',
$this->_params['username_field']);
}
try {
return $this->_db->selectValues($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Auth_Exception($e);
}
}
/**
* Checks if a userId exists in the system.
*
* @param string $userId User ID for which to check
*
* @return boolean Whether or not the userId already exists.
*/
public function exists($userId)
{
/* Build the SQL query. */
$query = sprintf('SELECT 1 FROM %s WHERE %s = ?',
$this->_params['table'],
$this->_params['username_field']);
$values = array($userId);
try {
return (bool)$this->_db->selectValue($query, $values);
} catch (Horde_Db_Exception $e) {
return false;
}
}
/**
* Compare an encrypted password to a plaintext string to see if
* they match.
*
* @param string $encrypted The crypted password to compare against.
* @param string $plaintext The plaintext password to verify.
*
* @return boolean True if matched, false otherwise.
*/
protected function _comparePasswords($encrypted, $plaintext)
{
return $encrypted == Horde_Auth::getCryptedPassword($plaintext,
$encrypted,
$this->_params['encryption'],
$this->_params['show_encryption']);
}
/**
* Calculate a timestamp and return it along with the field name
*
* @param string $type The timestamp parameter.
*
* @return integer 'timestamp' intended field value or null
*/
private function _calc_expiration($type)
{
if (empty($this->_params[$type . '_expiration_window'])) {
return null;
} else {
$now = new Horde_Date(time());
return $now->add(array('mday' => $this->_params[$type.'_expiration_window']))->timestamp();
}
}
}
Horde_Auth-2.1.11/lib/Horde/Auth/Translation.php 0000664 0001750 0001750 00000001671 12653661601 017454 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* Horde_Auth_Translation is the translation wrapper class for Horde_Auth.
*
* @author Jan Schneider
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth_Translation extends Horde_Translation_Autodetect
{
/**
* The translation domain
*
* @var string
*/
protected static $_domain = 'Horde_Auth';
/**
* The absolute PEAR path to the translations for the default gettext handler.
*
* @var string
*/
protected static $_pearDirectory = '@data_dir@';
}
Horde_Auth-2.1.11/lib/Horde/Auth/X509.php 0000664 0001750 0001750 00000011631 12653661601 015620 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
* @since 2.0.7
*/
/**
* The Horde_Auth_X509 class provides an authentication driver for using X509
* client certificates. Since X509 certificates do not provide the password,
* if the server setup requires the use of per-user passwords, a callback
* function may be passed to obtain it from.
*
* @author Michael J Rubinsky
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
* @since 2.0.7
*/
class Horde_Auth_X509 extends Horde_Auth_Base
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'transparent' => true
);
/**
* Constructor.
*
* @param array $params Parameters:
* - password: (string) If available, the password to use for the session.
* DEFAULT: no password used.
* - username_field: (string) Name of the $_SERVER field that
* the username can be found in. DEFAULT: 'SSL_CLIENT_S_DN_EMAILADDRESS'.
* - certificate_field: (string) Name of the $_SERVER field that contains
* the full certificate. DEFAULT: 'SSL_CLIENT_CERT'
* - ignore_purpose: (boolean) If true, will ignore any usage restrictions
* on the presented client certificate. I.e., if openssl_x509_checkpurpose
* returns false, authentication may still proceed. DEFAULT: false - ONLY
* ENABLE THIS IF YOU KNOW WHY YOU ARE DOING SO.
* - filter: (array) An array where the keys are field names and the
* values are the values those certificate fields MUST
* match to be considered valid. Keys in the format of
* fieldone:fieldtwo will be taken as parent:child.
* DEFAULT: no additionachecks applied.
*
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
$params = array_merge(array(
'password' => false,
'username_field' => 'SSL_CLIENT_S_DN_CN',
'certificate_field' => 'SSL_CLIENT_CERT',
'ignore_purpose' => true,
'filter' => array()
), $params);
parent::__construct($params);
}
/**
* Not implemented.
*
* @param string $userId The userID to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
throw new Horde_Auth_Exception('Unsupported.');
}
/**
* Automatic authentication: checks if the username is set in the
* configured header.
*
* @return boolean Whether or not the client is allowed.
*/
public function transparent()
{
if (!is_callable('openssl_x509_parse')) {
throw new Horde_Auth_Exception('SSL not enabled on server.');
}
if (empty($_SERVER[$this->_params['username_field']]) ||
empty($_SERVER[$this->_params['certificate_field']])) {
return false;
}
// Valid for client auth?
$cert = openssl_x509_read($_SERVER[$this->_params['certificate_field']]);
if (!$this->_params['ignore_purpose'] &&
!openssl_x509_checkpurpose($cert, X509_PURPOSE_SSL_CLIENT) &&
!openssl_x509_checkpurpose($cert, X509_PURPOSE_ANY)) {
return false;
}
$c_parsed = openssl_x509_parse($cert);
foreach ($this->_params['filter'] as $key => $value) {
$keys = explode(':', $key);
$c = $c_parsed;
foreach ($keys as $k) {
$c = $c[$k];
}
if ($c != $value) {
return false;
}
}
// Handle any custom validation added by sub classes.
if (!$this->_validate($cert)) {
return false;
}
// Free resources.
openssl_x509_free($cert);
// Set credentials
$this->setCredential('userId', $_SERVER[$this->_params['username_field']]);
$cred = array('certificate_id' => $c_parsed['hash']);
if (!empty($this->_params['password'])) {
$cred['password'] = $this->_params['password'];
}
$this->setCredential('credentials', $cred);
return true;
}
/**
* Perform additional validation of certificate fields.
*
* @return boolean
*/
protected function _validate($certificate)
{
return true;
}
}
Horde_Auth-2.1.11/lib/Horde/Auth.php 0000664 0001750 0001750 00000047773 12653661601 015173 0 ustar jan jan
* @author Michael Slusarz
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
/**
* The Horde_Auth class provides some useful authentication-related utilities
* and constants for the Auth package.
*
* @author Chuck Hagenbuch
* @author Michael Slusarz
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
*/
class Horde_Auth
{
/**
* Authentication failure reasons.
*
*
* REASON_BADLOGIN - Bad username and/or password
* REASON_FAILED - Login failed
* REASON_EXPIRED - Password has expired
* REASON_LOGOUT - Logout due to user request
* REASON_MESSAGE - Logout with custom message
* REASON_SESSION - Logout due to session expiration
* REASON_LOCKED - User is locked
*
*/
const REASON_BADLOGIN = 1;
const REASON_FAILED = 2;
const REASON_EXPIRED = 3;
const REASON_LOGOUT = 4;
const REASON_MESSAGE = 5;
const REASON_SESSION = 6;
const REASON_LOCKED = 7;
/**
* 64 characters that are valid for APRMD5 passwords.
*/
const APRMD5_VALID = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
/**
* Characters used when generating a password.
*/
const VOWELS = 'aeiouy';
const CONSONANTS = 'bcdfghjklmnpqrstvwxz';
const NUMBERS = '0123456789';
/**
* Attempts to return a concrete Horde_Auth_Base instance based on
* $driver.
*
* @deprecated
*
* @param string $driver Either a driver name, or the full class name to
* use (class must extend Horde_Auth_Base).
* @param array $params A hash containing any additional configuration
* or parameters a subclass might need.
*
* @return Horde_Auth_Base The newly created concrete instance.
* @throws Horde_Auth_Exception
*/
public static function factory($driver, $params = null)
{
/* Base drivers (in Auth/ directory). */
$class = __CLASS__ . '_' . Horde_String::ucfirst($driver);
if (@class_exists($class)) {
return new $class($params);
}
/* Explicit class name, */
$class = $driver;
if (@class_exists($class)) {
return new $class($params);
}
throw new Horde_Auth_Exception(__CLASS__ . ': Class definition of ' . $driver . ' not found.');
}
/**
* Formats a password using the current encryption.
*
* @param string $plaintext The plaintext password to encrypt.
* @param string $salt The salt to use to encrypt the password.
* If not present, a new salt will be
* generated.
* @param string $encryption The kind of pasword encryption to use.
* Defaults to md5-hex.
* @param boolean $show_encrypt Some password systems prepend the kind of
* encryption to the crypted password ({SHA},
* etc). Defaults to false.
*
* @return string The encrypted password.
*/
public static function getCryptedPassword($plaintext, $salt = '',
$encryption = 'md5-hex',
$show_encrypt = false)
{
/* Get the salt to use. */
$salt = self::getSalt($encryption, $salt, $plaintext);
/* Encrypt the password. */
switch ($encryption) {
case 'aprmd5':
$length = strlen($plaintext);
$context = $plaintext . '$apr1$' . $salt;
$binary = pack('H*', hash('md5', $plaintext . $salt . $plaintext));
for ($i = $length; $i > 0; $i -= 16) {
$context .= substr($binary, 0, ($i > 16 ? 16 : $i));
}
for ($i = $length; $i > 0; $i >>= 1) {
$context .= ($i & 1) ? chr(0) : $plaintext[0];
}
$binary = pack('H*', hash('md5', $context));
for ($i = 0; $i < 1000; ++$i) {
$new = ($i & 1) ? $plaintext : substr($binary, 0, 16);
if ($i % 3) {
$new .= $salt;
}
if ($i % 7) {
$new .= $plaintext;
}
$new .= ($i & 1) ? substr($binary, 0, 16) : $plaintext;
$binary = pack('H*', hash('md5', $new));
}
$p = array();
for ($i = 0; $i < 5; $i++) {
$k = $i + 6;
$j = $i + 12;
if ($j == 16) {
$j = 5;
}
$p[] = self::_toAPRMD5((ord($binary[$i]) << 16) |
(ord($binary[$k]) << 8) |
(ord($binary[$j])),
5);
}
return '$apr1$' . $salt . '$' . implode('', $p) . self::_toAPRMD5(ord($binary[11]), 3);
case 'crypt':
case 'crypt-des':
case 'crypt-md5':
case 'crypt-sha256':
case 'crypt-sha512':
case 'crypt-blowfish':
return ($show_encrypt ? '{crypt}' : '') . crypt($plaintext, $salt);
case 'joomla-md5':
return md5($plaintext . $salt) . ':' . $salt;
case 'md5-base64':
$encrypted = base64_encode(pack('H*', hash('md5', $plaintext)));
return $show_encrypt ? '{MD5}' . $encrypted : $encrypted;
case 'msad':
return Horde_String::convertCharset('"' . $plaintext . '"', 'ISO-8859-1', 'UTF-16LE');
case 'mysql':
$encrypted = '*' . Horde_String::upper(sha1(sha1($plaintext, true), false));
return $show_encrypt ? '{MYSQL}' . $encrypted : $encrypted;
case 'plain':
return $plaintext;
case 'sha':
case 'sha1':
$encrypted = base64_encode(pack('H*', hash('sha1', $plaintext)));
return $show_encrypt ? '{SHA}' . $encrypted : $encrypted;
case 'sha256':
case 'ssha256':
$encrypted = base64_encode(pack('H*', hash('sha256', $plaintext . $salt)) . $salt);
return $show_encrypt ? '{SSHA256}' . $encrypted : $encrypted;
case 'smd5':
$encrypted = base64_encode(pack('H*', hash('md5', $plaintext . $salt)) . $salt);
return $show_encrypt ? '{SMD5}' . $encrypted : $encrypted;
case 'ssha':
$encrypted = base64_encode(pack('H*', hash('sha1', $plaintext . $salt)) . $salt);
return $show_encrypt ? '{SSHA}' . $encrypted : $encrypted;
case 'md5-hex':
default:
return ($show_encrypt) ? '{MD5}' . hash('md5', $plaintext) : hash('md5', $plaintext);
}
}
/**
* Returns a salt for the appropriate kind of password encryption.
* Optionally takes a seed and a plaintext password, to extract the seed
* of an existing password, or for encryption types that use the plaintext
* in the generation of the salt.
*
* @param string $encryption The kind of pasword encryption to use.
* Defaults to md5-hex.
* @param string $seed The seed to get the salt from (probably a
* previously generated password). Defaults to
* generating a new seed.
* @param string $plaintext The plaintext password that we're generating
* a salt for. Defaults to none.
*
* @return string The generated or extracted salt.
*/
public static function getSalt($encryption = 'md5-hex', $seed = '',
$plaintext = '')
{
switch ($encryption) {
case 'aprmd5':
if ($seed) {
return substr(preg_replace('/^\$apr1\$(.{8}).*/', '\\1', $seed), 0, 8);
} else {
$salt = '';
$valid = self::APRMD5_VALID;
for ($i = 0; $i < 8; ++$i) {
$salt .= $valid[mt_rand(0, 63)];
}
return $salt;
}
case 'crypt':
case 'crypt-des':
return $seed
? substr(preg_replace('|^{crypt}|i', '', $seed), 0, 2)
: substr(base64_encode(hash('md5', mt_rand(), true)), 0, 2);
case 'crypt-blowfish':
return $seed
? preg_replace('|^(?:{crypt})?(\$2.?\$(?:\d\d\$)?[0-9A-Za-z./]{22}).*|i', '$1', $seed)
: '$2$' . substr(base64_encode(hash('md5', sprintf('%08X%08X%08X', mt_rand(), mt_rand(), mt_rand()), true)), 0, 21) . '$';
case 'crypt-md5':
return $seed
? substr(preg_replace('|^{crypt}|i', '', $seed), 0, 12)
: '$1$' . base64_encode(hash('md5', sprintf('%08X%08X', mt_rand(), mt_rand()), true)) . '$';
case 'crypt-sha256':
return $seed
? substr(preg_replace('|^{crypt}|i', '', $seed), 0, strrpos($seed, '$'))
: '$5$' . base64_encode(hash('md5', sprintf('%08X%08X%08X', mt_rand(), mt_rand(), mt_rand()), true)) . '$';
case 'crypt-sha512':
return $seed
? substr(preg_replace('|^{crypt}|i', '', $seed), 0, strrpos($seed, '$'))
: '$6$' . base64_encode(hash('md5', sprintf('%08X%08X%08X', mt_rand(), mt_rand(), mt_rand()), true)) . '$';
case 'joomla-md5':
$split = preg_split('/:/', $seed );
return $split ? $split[1] : '';
case 'sha256':
case 'ssha256':
return $seed
? substr(base64_decode(preg_replace('|^{SSHA256}|i', '', $seed)), 32)
: substr(pack('H*', hash('sha256', substr(pack('h*', hash('md5', mt_rand())), 0, 8) . $plaintext)), 0, 4);
case 'smd5':
return $seed
? substr(base64_decode(preg_replace('|^{SMD5}|i', '', $seed)), 16)
: substr(pack('H*', hash('md5', substr(pack('h*', hash('md5', mt_rand())), 0, 8) . $plaintext)), 0, 4);
case 'ssha':
return $seed
? substr(base64_decode(preg_replace('|^{SSHA}|i', '', $seed)), 20)
: substr(pack('H*', hash('sha1', substr(pack('h*', hash('md5', mt_rand())), 0, 8) . $plaintext)), 0, 4);
default:
return '';
}
}
/**
* Converts to allowed 64 characters for APRMD5 passwords.
*
* @param string $value The value to convert
* @param integer $count The number of iterations
*
* @return string $value converted to the 64 MD5 characters.
*/
protected static function _toAPRMD5($value, $count)
{
$aprmd5 = '';
$count = abs($count);
$valid = self::APRMD5_VALID;
while (--$count) {
$aprmd5 .= $valid[$value & 0x3f];
$value >>= 6;
}
return $aprmd5;
}
/**
* Generates a random, hopefully pronounceable, password. This can be used
* when resetting automatically a user's password.
*
* @return string A random password
*/
public static function genRandomPassword()
{
/* Alternate consonant and vowel random chars with two random numbers
* at the end. This should produce a fairly pronounceable password. */
return substr(self::CONSONANTS, mt_rand(0, strlen(self::CONSONANTS) - 1), 1) .
substr(self::VOWELS, mt_rand(0, strlen(self::VOWELS) - 1), 1) .
substr(self::CONSONANTS, mt_rand(0, strlen(self::CONSONANTS) - 1), 1) .
substr(self::VOWELS, mt_rand(0, strlen(self::VOWELS) - 1), 1) .
substr(self::CONSONANTS, mt_rand(0, strlen(self::CONSONANTS) - 1), 1) .
substr(self::NUMBERS, mt_rand(0, strlen(self::NUMBERS) - 1), 1) .
substr(self::NUMBERS, mt_rand(0, strlen(self::NUMBERS) - 1), 1);
}
/**
* Checks whether a password matches some expected policy.
*
* @param string $password A password.
* @param array $policy A configuration with policy rules. Supported
* rules:
*
* - minLength: Minimum length of the password
* - maxLength: Maximum length of the password
* - maxSpace: Maximum number of white space characters
*
* The following are the types of characters required in a
* password. Either specific characters, character classes,
* or both can be required. Specific types are:
*
* - minUpper: Minimum number of uppercase characters
* - minLower: Minimum number of lowercase characters
* - minNumeric: Minimum number of numeric characters (0-9)
* - minAlphaNum: Minimum number of alphanumeric characters
* - minAlpha: Minimum number of alphabetic characters
* - minSymbol: Minimum number of punctuation / symbol characters
* - minNonAlpha: Minimum number of non-alphabetic characters
*
* Alternatively (or in addition to), the minimum number of
* character classes can be configured by setting the
* following. The valid range is 0 through 4 character
* classes may be required for a password. The classes are:
* 'upper', 'lower', 'number', and 'symbol'. For example: A
* password of 'p@ssw0rd' satisfies three classes ('number',
* 'lower', and 'symbol'), while 'passw0rd' only satisfies two
* classes ('lower' and 'number').
*
* - minClasses: Minimum number (0 through 4) of character
* classes.
*
* @throws Horde_Auth_Exception if the password does not match the policy.
*/
public static function checkPasswordPolicy($password, array $policy)
{
// Check max/min lengths if specified in the policy.
if (isset($policy['minLength']) &&
strlen($password) < $policy['minLength']) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::t("The password must be at least %d characters long!"), $policy['minLength']));
}
if (isset($policy['maxLength']) &&
strlen($password) > $policy['maxLength']) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::t("The password is too long; passwords may not be more than %d characters long!"), $policy['maxLength']));
}
// Dissect the password in a localized way.
$classes = array();
$alpha = $nonalpha = $alnum = $num = $upper = $lower = $space = $symbol = 0;
for ($i = 0; $i < strlen($password); $i++) {
$char = substr($password, $i, 1);
if (ctype_lower($char)) {
$lower++; $alpha++; $alnum++; $classes['lower'] = 1;
} elseif (ctype_upper($char)) {
$upper++; $alpha++; $alnum++; $classes['upper'] = 1;
} elseif (ctype_digit($char)) {
$num++; $nonalpha++; $alnum++; $classes['number'] = 1;
} elseif (ctype_punct($char)) {
$symbol++; $nonalpha++; $classes['symbol'] = 1;
} elseif (ctype_space($char)) {
$space++; $classes['symbol'] = 1;
}
}
// Check reamaining password policy options.
if (isset($policy['minUpper']) && $policy['minUpper'] > $upper) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::ngettext("The password must contain at least %d uppercase character.", "The password must contain at least %d uppercase characters.", $policy['minUpper']), $policy['minUpper']));
}
if (isset($policy['minLower']) && $policy['minLower'] > $lower) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::ngettext("The password must contain at least %d lowercase character.", "The password must contain at least %d lowercase characters.", $policy['minLower']), $policy['minLower']));
}
if (isset($policy['minNumeric']) && $policy['minNumeric'] > $num) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::ngettext("The password must contain at least %d numeric character.", "The password must contain at least %d numeric characters.", $policy['minNumeric']), $policy['minNumeric']));
}
if (isset($policy['minAlpha']) && $policy['minAlpha'] > $alpha) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::ngettext("The password must contain at least %d alphabetic character.", "The password must contain at least %d alphabetic characters.", $policy['minAlpha']), $policy['minAlpha']));
}
if (isset($policy['minAlphaNum']) && $policy['minAlphaNum'] > $alnum) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::ngettext("The password must contain at least %d alphanumeric character.", "The password must contain at least %d alphanumeric characters.", $policy['minAlphaNum']), $policy['minAlphaNum']));
}
if (isset($policy['minNonAlpha']) && $policy['minNonAlpha'] > $nonalpha) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::ngettext("The password must contain at least %d numeric or special character.", "The password must contain at least %d numeric or special characters.", $policy['minNonAlpha']), $policy['minNonAlpha']));
}
if (isset($policy['minClasses']) && $policy['minClasses'] > array_sum($classes)) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::t("The password must contain at least %d different types of characters. The types are: lower, upper, numeric, and symbols."), $policy['minClasses']));
}
if (isset($policy['maxSpace']) && $policy['maxSpace'] < $space) {
if ($policy['maxSpace'] > 0) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::t("The password must contain less than %d whitespace characters."), $policy['maxSpace'] + 1));
}
throw new Horde_Auth_Exception(Horde_Auth_Translation::t("The password must not contain whitespace characters."));
}
if (isset($policy['minSymbol']) && $policy['minSymbol'] > $symbol) {
throw new Horde_Auth_Exception(sprintf(Horde_Auth_Translation::ngettext("The password must contain at least %d symbol character.", "The password must contain at least %d symbol characters.", $policy['minSymbol']), $policy['minSymbol']));
}
}
/**
* Checks whether a password is too similar to a dictionary of strings.
*
* @param string $password A password.
* @param array $dict A dictionary to check for similarity, for
* example the user name or an old password.
* @param float $max The maximum allowed similarity in percent.
*
* @throws Horde_Auth_Exception if the password is too similar.
*/
public static function checkPasswordSimilarity($password, array $dict,
$max = 80)
{
// Check for pass == dict, simple reverse strings, etc.
foreach ($dict as $test) {
if ((strcasecmp($password, $test) == 0) ||
(strcasecmp($password, strrev($test)) == 0)) {
throw new Horde_Auth_Exception(Horde_Auth_Translation::t("The password is too simple to guess."));
}
}
// Check for percentages similarity also. This will catch very simple
// Things like "password" -> "password2" or "xpasssword"...
// Also, don't allow simple changing of capitalization to pass
foreach ($dict as $test) {
similar_text(Horde_String::lower($password), Horde_String::lower($test), $percent);
if ($percent > $max) {
throw new Horde_Auth_Exception(Horde_Auth_Translation::t("The password is too simple to guess."));
}
}
}
}
Horde_Auth-2.1.11/locale/da/LC_MESSAGES/Horde_Auth.mo 0000664 0001750 0001750 00000006232 12653661601 017722 0 ustar jan jan x L y $ 1 x | w v r u p v o = 4 $ + Y ( L 5 0 r O G d
O |
w
W D e 1 ' 4 \ |
The password is too long; passwords may not be more than %d characters long! The password is too simple to guess. The password must be at least %d characters long! The password must contain at least %d alphabetic character. The password must contain at least %d alphabetic characters. The password must contain at least %d alphanumeric character. The password must contain at least %d alphanumeric characters. The password must contain at least %d different types of characters. The types are: lower, upper, numeric, and symbols. The password must contain at least %d lowercase character. The password must contain at least %d lowercase characters. The password must contain at least %d numeric character. The password must contain at least %d numeric characters. The password must contain at least %d numeric or special character. The password must contain at least %d numeric or special characters. The password must contain at least %d symbol character. The password must contain at least %d symbol characters. The password must contain at least %d uppercase character. The password must contain at least %d uppercase characters. The password must contain less than %d whitespace characters. The password must not contain whitespace characters. Your account has been locked for %d minutes Your account has been permanently locked Project-Id-Version: Horde_Auth
Report-Msgid-Bugs-To: dev@lists.horde.org
POT-Creation-Date: 2014-03-18 15:59+0100
PO-Revision-Date: 2014-03-19 20:32+0100
Last-Translator: Erling Preben Hansen
Language-Team: i18n@lists.horde.org
Language: da
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Plural-Forms: nplurals=2; plural=(n != 1);
Kodeordet er for langt: Kodeord må ikke være mere end %d karakterer langt! Kodeordet er for nemt at gætte. Kodeordet skal være mindst %d karakterer langt! Kodeordet skal indeholde mindst %d alfabetisk karakter. Kodeordet skal indeholde mindst %d alfabetiske karakterer. Kodeordet skal indeholde mindst %d tal. Kodeordet skal indeholde mindst %d tal. Kodeordet skal indeholde mindst %d forskellige typer af karakter. Typerne er: Små bogstaver, store bogstaver, tal og symboler. Kodeordet skal indeholde mindst %d lille bogstav. Kodeordet skal indeholde mindst %d små bogstaver. Kodeordet skal indeholde mindst %d tal. Kodeordet skal indeholde mindst %d tal. Kodeordet skal indeholde mindst %d tal eller special karakter. Kodeordet skal indeholde mindst %d tal eller karakterer. Kodeordet skal indeholde mindst %d symbol. Kodeordet skal indeholde mindst %d symboler. Kodeordet skal indeholde mindst %d stort bogstav. Kodeordet skal indeholde mindst %d store bogstaver. Kodeordet skal indeholde mindre end %d mellemrum. Kodeordet må ikke indeholde mellemrum. Din konto er lås i %d minutter Din konto er permanent låst. Horde_Auth-2.1.11/locale/da/LC_MESSAGES/Horde_Auth.po 0000664 0001750 0001750 00000010212 12653661601 017716 0 ustar jan jan # Danish translations for Horde_Auth package.
# Copyright (C) 2014 Horde LLC (http://www.horde.org/)
# This file is distributed under the same license as the Horde_Auth package.
# Erling Preben Hansen , 2013-2014.
#
msgid ""
msgstr ""
"Project-Id-Version: Horde_Auth\n"
"Report-Msgid-Bugs-To: dev@lists.horde.org\n"
"POT-Creation-Date: 2014-03-18 15:59+0100\n"
"PO-Revision-Date: 2014-03-19 20:32+0100\n"
"Last-Translator: Erling Preben Hansen \n"
"Language-Team: i18n@lists.horde.org\n"
"Language: da\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/Horde/Auth.php:375
#, php-format
msgid ""
"The password is too long; passwords may not be more than %d characters long!"
msgstr ""
"Kodeordet er for langt: Kodeord må ikke være mere end %d karakterer langt!"
#: lib/Horde/Auth.php:446 lib/Horde/Auth.php:456
msgid "The password is too simple to guess."
msgstr "Kodeordet er for nemt at gætte."
#: lib/Horde/Auth.php:371
#, php-format
msgid "The password must be at least %d characters long!"
msgstr "Kodeordet skal være mindst %d karakterer langt!"
#: lib/Horde/Auth.php:407
#, php-format
msgid "The password must contain at least %d alphabetic character."
msgid_plural "The password must contain at least %d alphabetic characters."
msgstr[0] "Kodeordet skal indeholde mindst %d alfabetisk karakter."
msgstr[1] "Kodeordet skal indeholde mindst %d alfabetiske karakterer."
#: lib/Horde/Auth.php:410
#, php-format
msgid "The password must contain at least %d alphanumeric character."
msgid_plural "The password must contain at least %d alphanumeric characters."
msgstr[0] "Kodeordet skal indeholde mindst %d tal."
msgstr[1] "Kodeordet skal indeholde mindst %d tal."
#: lib/Horde/Auth.php:416
#, php-format
msgid ""
"The password must contain at least %d different types of characters. The "
"types are: lower, upper, numeric, and symbols."
msgstr ""
"Kodeordet skal indeholde mindst %d forskellige typer af karakter. Typerne "
"er: Små bogstaver, store bogstaver, tal og symboler."
#: lib/Horde/Auth.php:401
#, php-format
msgid "The password must contain at least %d lowercase character."
msgid_plural "The password must contain at least %d lowercase characters."
msgstr[0] "Kodeordet skal indeholde mindst %d lille bogstav."
msgstr[1] "Kodeordet skal indeholde mindst %d små bogstaver."
#: lib/Horde/Auth.php:404
#, php-format
msgid "The password must contain at least %d numeric character."
msgid_plural "The password must contain at least %d numeric characters."
msgstr[0] "Kodeordet skal indeholde mindst %d tal."
msgstr[1] "Kodeordet skal indeholde mindst %d tal."
#: lib/Horde/Auth.php:413
#, php-format
msgid "The password must contain at least %d numeric or special character."
msgid_plural ""
"The password must contain at least %d numeric or special characters."
msgstr[0] "Kodeordet skal indeholde mindst %d tal eller special karakter."
msgstr[1] "Kodeordet skal indeholde mindst %d tal eller karakterer."
#: lib/Horde/Auth.php:425
#, php-format
msgid "The password must contain at least %d symbol character."
msgid_plural "The password must contain at least %d symbol characters."
msgstr[0] "Kodeordet skal indeholde mindst %d symbol."
msgstr[1] "Kodeordet skal indeholde mindst %d symboler."
#: lib/Horde/Auth.php:398
#, php-format
msgid "The password must contain at least %d uppercase character."
msgid_plural "The password must contain at least %d uppercase characters."
msgstr[0] "Kodeordet skal indeholde mindst %d stort bogstav."
msgstr[1] "Kodeordet skal indeholde mindst %d store bogstaver."
#: lib/Horde/Auth.php:420
#, php-format
msgid "The password must contain less than %d whitespace characters."
msgstr "Kodeordet skal indeholde mindre end %d mellemrum."
#: lib/Horde/Auth.php:422
msgid "The password must not contain whitespace characters."
msgstr "Kodeordet må ikke indeholde mellemrum."
#: lib/Horde/Auth/Base.php:156
#, php-format
msgid "Your account has been locked for %d minutes"
msgstr "Din konto er lås i %d minutter"
#: lib/Horde/Auth/Base.php:154
msgid "Your account has been permanently locked"
msgstr "Din konto er permanent låst."
Horde_Auth-2.1.11/locale/de/LC_MESSAGES/Horde_Auth.mo 0000664 0001750 0001750 00000006455 12653661601 017735 0 ustar jan jan x L y $ 1 x | w v r u p v o = 4 $ + Y ( N / &