Commit 5f8d03fe authored by Wolfgang Knopki's avatar Wolfgang Knopki
Browse files

added compatibility with simplesamlphp 1.19

parent 8e8e5b35
......@@ -12,216 +12,222 @@
* @package simpleSAMLphp
* @version $Id$
*/
class sspmod_sqlauthBcrypt_Auth_Source_SQL extends sspmod_core_Auth_UserPassBase {
/**
* The DSN we should connect to.
*/
private $dsn;
/**
* The username we should connect to the database with.
*/
private $username;
/**
* The password we should connect to the database with.
*/
private $password;
/**
* The query we should use to retrieve the attributes for the user.
*
* The username and password will be available as :username and :password.
*/
private $query;
/**
* The pepper used to generate the password hash.
*/
private $pepper;
/**
* The column holding the password hash.
*/
private $hash_column;
/**
* Constructor for this authentication source.
*
* @param array $info Information about this authentication source.
* @param array $config Configuration.
*/
public function __construct($info, $config) {
assert('is_array($info)');
assert('is_array($config)');
/* Call the parent constructor first, as required by the interface. */
parent::__construct($info, $config);
/* Make sure that all required parameters are present. */
foreach (array('dsn', 'username', 'password', 'query', 'pepper') as $param) {
if (!array_key_exists($param, $config)) {
throw new Exception('Missing required attribute \'' . $param .
'\' for authentication source ' . $this->authId);
}
if (!is_string($config[$param])) {
throw new Exception('Expected parameter \'' . $param .
'\' for authentication source ' . $this->authId .
' to be a string. Instead it was: ' .
var_export($config[$param], TRUE));
}
}
$this->dsn = $config['dsn'];
$this->username = $config['username'];
$this->password = $config['password'];
$this->query = $config['query'];
$this->pepper = $config['pepper'];
$this->hash_column = $config['hash_column'];
}
/**
* Create a database connection.
*
* @return PDO The database connection.
*/
private function connect() {
try {
$db = new PDO($this->dsn, $this->username, $this->password);
} catch (PDOException $e) {
throw new Exception('sqlauthBcrypt:' . $this->authId .
': - Failed to connect to \'' . $this->dsn . '\': '. $e->getMessage());
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$driver = explode(':', $this->dsn, 2);
$driver = strtolower($driver[0]);
/* Driver specific initialization. */
switch ($driver) {
case 'mysql':
/* Use UTF-8. */
$db->exec("SET NAMES 'utf8'");
break;
case 'pgsql':
/* Use UTF-8. */
$db->exec("SET NAMES 'UTF8'");
break;
}
return $db;
}
/**
* Attempt to log in using the given username and password.
*
* On a successful login, this function should return the users attributes. On failure,
* it should throw an exception. If the error was caused by the user entering the wrong
* username or password, a SimpleSAML_Error_Error('WRONGUSERPASS') should be thrown.
*
* Note that both the username and the password are UTF-8 encoded.
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
* @return array Associative array with the users attributes.
*/
protected function login($username, $password) {
assert('is_string($username)');
assert('is_string($password)');
$db = $this->connect();
try {
$sth = $db->prepare($this->query);
} catch (PDOException $e) {
throw new Exception('sqlauthBcrypt:' . $this->authId .
': - Failed to prepare query: ' . $e->getMessage());
}
try {
$res = $sth->execute(array('username' => $username));
} catch (PDOException $e) {
throw new Exception('sqlauthBcrypt:' . $this->authId .
': - Failed to execute query: ' . $e->getMessage());
}
try {
$data = $sth->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
throw new Exception('sqlauth:' . $this->authId .
': - Failed to fetch result set: ' . $e->getMessage());
}
SimpleSAML_Logger::info('sqlauthBcrypt:' . $this->authId .
': Got ' . count($data) . ' rows from database');
if (count($data) === 0) {
/* No rows returned - invalid username */
SimpleSAML_Logger::error('sqlauthBcrypt:' . $this->authId .
': No rows in result set. Wrong username or sqlauthBcrypt is misconfigured.');
throw new SimpleSAML_Error_Error('WRONGUSERPASS');
}
/* Validate stored password hash (must be in first row of resultset) */
$password_hash = $data[0][$this->hash_column];
if ($password_hash !== crypt($password.$this->pepper, $password_hash)) {
/* Invalid password */
SimpleSAML_Logger::error('sqlauthBcrypt:' . $this->authId .
': Hash does not match. Wrong password or sqlauthBcrypt is misconfigured.');
throw new SimpleSAML_Error_Error('WRONGUSERPASS');
}
/* Extract attributes. We allow the resultset to consist of multiple rows. Attributes
* which are present in more than one row will become multivalued. NULL values and
* duplicate values will be skipped. All values will be converted to strings.
*/
$attributes = array();
foreach ($data as $row) {
foreach ($row as $name => $value) {
if ($value === NULL) {
continue;
}
if ($name === $this->hash_column) {
/* Don't add password hash to attributes */
continue;
}
$value = (string)$value;
if (!array_key_exists($name, $attributes)) {
$attributes[$name] = array();
}
if (in_array($value, $attributes[$name], TRUE)) {
/* Value already exists in attribute. */
continue;
}
$attributes[$name][] = $value;
}
}
SimpleSAML_Logger::info('sqlauthBcrypt:' . $this->authId .
': Attributes: ' . implode(',', array_keys($attributes)));
return $attributes;
}
/*class sspmod_sqlauthBcrypt_Auth_Source_SQL extends sspmod_core_Auth_UserPassBase {*/
namespace SimpleSAML\Module\sqlauthbcrypt\Auth\Source;
class sql extends \SimpleSAML\Module\core\Auth\UserPassBase {
/**
* The DSN we should connect to.
*/
private $dsn;
/**
* The username we should connect to the database with.
*/
private $username;
/**
* The password we should connect to the database with.
*/
private $password;
/**
* The query we should use to retrieve the attributes for the user.
*
* The username and password will be available as :username and :password.
*/
private $query;
/**
* The pepper used to generate the password hash.
*/
private $pepper;
/**
* The column holding the password hash.
*/
private $hash_column;
/**
* Constructor for this authentication source.
*
* @param array $info Information about this authentication source.
* @param array $config Configuration.
*/
public function __construct($info, $config) {
assert('is_array($info)');
assert('is_array($config)');
/* Call the parent constructor first, as required by the interface. */
parent::__construct($info, $config);
/* Make sure that all required parameters are present. */
foreach (array('dsn', 'username', 'password', 'query', 'pepper') as $param) {
if (!array_key_exists($param, $config)) {
throw new \Exception('Missing required attribute \'' . $param .
'\' for authentication source ' . $this->authId);
}
if (!is_string($config[$param])) {
throw new \Exception('Expected parameter \'' . $param .
'\' for authentication source ' . $this->authId .
' to be a string. Instead it was: ' .
var_export($config[$param], TRUE));
}
}
$this->dsn = $config['dsn'];
$this->username = $config['username'];
$this->password = $config['password'];
$this->query = $config['query'];
$this->pepper = $config['pepper'];
$this->hash_column = $config['hash_column'];
}
/**
* Create a database connection.
*
* @return PDO The database connection.
*/
private function connect() {
try {
$db = new \PDO($this->dsn, $this->username, $this->password);
} catch (\PDOException $e) {
throw new \Exception('sqlauthBcrypt:' . $this->authId .
': - Failed to connect to \'' . $this->dsn . '\': '. $e->getMessage());
}
$db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$driver = explode(':', $this->dsn, 2);
$driver = strtolower($driver[0]);
/* Driver specific initialization. */
switch ($driver) {
case 'mysql':
/* Use UTF-8. */
$db->exec("SET NAMES 'utf8'");
break;
case 'pgsql':
/* Use UTF-8. */
$db->exec("SET NAMES 'UTF8'");
break;
}
return $db;
}
/**
* Attempt to log in using the given username and password.
*
* On a successful login, this function should return the users attributes. On failure,
* it should throw an exception. If the error was caused by the user entering the wrong
* username or password, a SimpleSAML_Error_Error('WRONGUSERPASS') should be thrown.
*
* Note that both the username and the password are UTF-8 encoded.
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
* @return array Associative array with the users attributes.
*/
protected function login(string $username,string $password):array {
assert('is_string($username)');
assert('is_string($password)');
$db = $this->connect();
try {
$sth = $db->prepare($this->query);
} catch (\PDOException $e) {
throw new \Exception('sqlauthBcrypt:' . $this->authId .
': - Failed to prepare query: ' . $e->getMessage());
}
try {
$res = $sth->execute(array('username' => $username));
} catch ( \PDOException $e) {
throw new \Exception('sqlauthBcrypt:' . $this->authId .
': - Failed to execute query: ' . $e->getMessage());
}
try {
$data = $sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (\PDOException $e) {
throw new \Exception('sqlauth:' . $this->authId .
': - Failed to fetch result set: ' . $e->getMessage());
}
\SimpleSAML\Logger::info('sqlauthBcrypt:' . $this->authId .
': Got ' . count($data) . ' rows from database');
if (count($data) === 0) {
/* No rows returned - invalid username */
\SimpleSAML\Logger::error('sqlauthBcrypt:' . $this->authId .
': No rows in result set. Wrong username or sqlauthBcrypt is misconfigured.');
throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
}
/* Validate stored password hash (must be in first row of resultset) */
$password_hash = $data[0][$this->hash_column];
if ($password_hash !== crypt($password.$this->pepper, $password_hash)) {
/* Invalid password */
\SimpleSAML\Logger::error('sqlauthBcrypt:' . $this->authId .
': Hash does not match. Wrong password or sqlauthBcrypt is misconfigured.');
throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
}
/* Extract attributes. We allow the resultset to consist of multiple rows. Attributes
* which are present in more than one row will become multivalued. NULL values and
* duplicate values will be skipped. All values will be converted to strings.
*/
$attributes = array();
foreach ($data as $row) {
foreach ($row as $name => $value) {
if ($value === NULL) {
continue;
}
if ($name === $this->hash_column) {
/* Don't add password hash to attributes */
continue;
}
$value = (string)$value;
if (!array_key_exists($name, $attributes)) {
$attributes[$name] = array();
}
if (in_array($value, $attributes[$name], TRUE)) {
/* Value already exists in attribute. */
continue;
}
$attributes[$name][] = $value;
}
}
\SimpleSAML\Logger::info('sqlauthBcrypt:' . $this->authId .
': Attributes: ' . implode(',', array_keys($attributes)));
return $attributes;
}
}
?>
\ No newline at end of file
?>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment