Files
server/usr/share/psa-horde/passwd/lib/Driver/Sql.php
2026-01-07 20:52:11 +01:00

205 lines
6.4 KiB
PHP

<?php
/**
* Copyright 2000-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (GPL). If you
* did not receive this file, see http://www.horde.org/licenses/gpl.
*
* @category Horde
* @copyright 2000-2017 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package Passwd
*/
/**
* Changes a password stored in an SQL database.
*
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @author Mattias Webjörn Eriksson <mattias@webjorn.org>
* @author Ilya Krel <mail@krel.org>
* @author Ralf Lang <lang@b1-systems.de> (H4 conversion)
* @author Eric Jon Rostetter <eric.rostetter@physics.utexas.edu>
* @author Tjeerd van der Zee <admin@xar.nl>
* @category Horde
* @copyright 2000-2017 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package Passwd
*/
class Passwd_Driver_Sql extends Passwd_Driver
{
/**
* Handle for the current database connection.
*
* @var Horde_Db_Adapter
*/
protected $_db;
/**
* @param array $params Driver parameters:
* - db: (Horde_Db_Adapter; REQUIRED) A DB Adapter object.
* - encryption: (string) The encryption type.
* - pass_col: (string) The table column for password.
* - query_lookup: (string) Should we use a custom query for lookup?
* - query_modify: (string) Should we use a custom query for changing?
* - show_encryption: (boolean) Prepend the encryption type to the
* password?
* - table: (string) The name of the user database table.
* - user_col: (string) The table column for user name.
*/
public function __construct(array $params = array())
{
if (isset($params['db'])) {
$this->_db = $params['db'];
unset($params['db']);
} else {
throw new InvalidArgumentException('Missing required Horde_Db_Adapter object');
}
/* These default to matching the Auth_Sql defaults. */
parent::__construct(array_merge(array(
'encryption' => 'ssha',
'pass_col' => 'user_pass',
'query_lookup' => false,
'query_modify' => false,
'show_encryption' => false,
'table' => 'horde_users',
'user_col' => 'user_uid'
), $params));
}
/**
* Finds out if a username and password is valid.
*
* @param string $userID The userID to check.
* @param string $oldpass An old password to check.
*
* @throws Passwd_Exception
*/
protected function _lookup($user, $oldpass)
{
if (!empty($this->_params['query_lookup'])) {
list($sql, $values) = $this->_parseQuery($this->_params['query_lookup'], $user, $oldpass);
} else {
/* Build the SQL query. */
$sql = 'SELECT ' . $this->_params['pass_col'] . ' FROM ' . $this->_params['table'] .
' WHERE ' . $this->_params['user_col'] . ' = ?';
$values = array($user);
}
/* Run query. */
try {
$result = $this->_db->selectOne($sql, $values);
} catch (Horde_Db_Exception $e) {
throw new Passwd_Exception($e);
}
if (!is_array($result)) {
throw new Passwd_Exception(_("User not found"));
}
/* Check the passwords match. */
$this->_comparePasswords($result[$this->_params['pass_col']], $oldpass);
}
/**
* Modifies a SQL password record for a user.
*
* @param string $user The user whose record we will udpate.
* @param string $newpass The new password value to set.
*
* @throws Passwd_Exception
*/
protected function _modify($user, $newpass)
{
if (!empty($this->_params['query_modify'])) {
list($sql, $values) = $this->_parseQuery($this->_params['query_modify'], $user, $newpass);
} else {
/* Encrypt the password. */
$newpass= $this->_encryptPassword($newpass);
/* Build the SQL query. */
$sql = 'UPDATE ' . $this->_params['table'] .
' SET ' . $this->_params['pass_col'] . ' = ?' .
' WHERE ' . $this->_params['user_col'] . ' = ?';
$values = array($newpass, $user);
}
/* Execute the query. */
try {
$this->_db->update($sql, $values);
} catch (Horde_Db_Exception $e) {
throw new Passwd_Exception($e);
}
}
/**
* Parses the string as an SQL query substituting placeholders for
* their values.
*
* @param string $string The string to process as a query.
* @param string $user The user to use for the %u placeholder.
* @param string $password The password to use for the %p and %e
* placeholders.
*
* @return string The processed SQL query.
*/
protected function _parseQuery($string, $user, $password)
{
$query = '';
$values = array();
$length = strlen($string);
@list($username, $domain) = explode('@', $user);
for ($i = 0; $i < $length; $i++) {
if ($string[$i] == '%' && !empty($string[$i + 1])) {
switch ($string[++$i]) {
case 'd':
$query .= '?';
$values[] = $domain;
break;
case 'u':
$query .= '?';
$values[] = $user;
break;
case 'U':
$query .= '?';
$values[] = $username;
break;
case 'p':
$query .= '?';
$values[] = $password;
break;
case 'e':
$query .= '?';
$values[] = $this->_encryptPassword($password);
break;
case '%':
$query .= '%';
break;
default:
$query .= '%' . $string[$i];
break;
}
} else {
$query .= $string[$i];
}
}
return array($query, $values);
}
/**
*/
protected function _changePassword($user, $oldpass, $newpass)
{
$this->_lookup($user, $oldpass);
$this->_modify($user, $newpass);
}
}