diff options
-rw-r--r-- | core/config/config.php | 1 | ||||
-rw-r--r-- | modules/auth/config/auth.php | 37 | ||||
-rw-r--r-- | modules/auth/config/basic_auth.php | 35 | ||||
-rw-r--r-- | modules/auth/helpers/auth_installer.php | 63 | ||||
-rw-r--r-- | modules/auth/libraries/Auth.php | 93 | ||||
-rw-r--r-- | modules/auth/libraries/drivers/Auth.php | 37 | ||||
-rw-r--r-- | modules/auth/libraries/drivers/Auth/Basic.php | 146 | ||||
-rw-r--r-- | modules/auth/models/password.php | 22 | ||||
-rw-r--r-- | modules/auth/tests/Auth_Installer_Test.php | 36 | ||||
-rw-r--r-- | modules/gallery_unit_test/controllers/test.php | 2 |
10 files changed, 472 insertions, 0 deletions
diff --git a/core/config/config.php b/core/config/config.php index b57a4b71..dafd107f 100644 --- a/core/config/config.php +++ b/core/config/config.php @@ -129,4 +129,5 @@ $config['modules'] = array MODPATH . 'user', MODPATH . 'info', MODPATH . 'gmaps', + MODPATH . 'auth', ); diff --git a/modules/auth/config/auth.php b/modules/auth/config/auth.php new file mode 100644 index 00000000..b63cc114 --- /dev/null +++ b/modules/auth/config/auth.php @@ -0,0 +1,37 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Name of the driver to be used for handling user authentication and password management + */ +$config['driver'] = 'Basic'; + +/** + * Set the auto-login (remember me) cookie lifetime, in seconds. The default + * lifetime is two weeks. + */ +$config['lifetime'] = 1209600; + +/** + * Array of modules that this module depends on. + * + * Not currently used, but provided for documentation purposes + */ +$config['depends'] = array('user'); diff --git a/modules/auth/config/basic_auth.php b/modules/auth/config/basic_auth.php new file mode 100644 index 00000000..9b45153e --- /dev/null +++ b/modules/auth/config/basic_auth.php @@ -0,0 +1,35 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Type of hash to use for passwords. Any algorithm supported by the hash function + * can be used here. Note that the length of your password is determined by the + * hash type + the number of salt characters. + * @see http://php.net/hash + * @see http://php.net/hash_algos + */ +$config['hash_method'] = 'sha1'; + +/** + * Defines the hash offsets to insert the salt at. The password hash length + * will be increased by the total number of offsets. + */ +$config['salt_pattern'] = '1, 3, 5, 9, 14, 15, 20, 21, 28, 30'; + diff --git a/modules/auth/helpers/auth_installer.php b/modules/auth/helpers/auth_installer.php new file mode 100644 index 00000000..b1477ff8 --- /dev/null +++ b/modules/auth/helpers/auth_installer.php @@ -0,0 +1,63 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +class auth_installer { + public static function install() { + Kohana::log("debug", "auth_installer::install"); + $db = Database::instance(); + try { + $base_version = ORM::factory("module")->where("name", "auth")->find()->version; + } catch (Exception $e) { + if ($e->getCode() == 44) { + $base_version = 0; + } else { + Kohana::log("error", $e); + throw $e; + } + } + Kohana::log("debug", "base_version: $base_version"); + + if ($base_version == 0) { + $db->query("CREATE TABLE IF NOT EXISTS `passwords` ( + `id` int(9) NOT NULL auto_increment, + `user_id` int(9) NOT NULL, + `password` varchar(1128) NOT NULL, + `logins` int(10) unsigned NOT NULL default '0', + `last_login` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY (`user_id`)) + ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + + $user_module = ORM::factory("module")->where("name", "auth")->find(); + $user_module->name = "auth"; + $user_module->version = 1; + $user_module->save(); + + $user = ORM::factory("user")->where("name", "admin")->find(); + Auth::instance()->set_user_password($user->id, "admin"); + } + } + + public static function uninstall() { + $db = Database::instance(); + $db->query("DROP TABLE IF EXISTS `passwords`;"); + $auth_module = ORM::factory("module")->where("name", "auth")->find(); + $auth_module->delete(); + } +}
\ No newline at end of file diff --git a/modules/auth/libraries/Auth.php b/modules/auth/libraries/Auth.php new file mode 100644 index 00000000..9bc59ec7 --- /dev/null +++ b/modules/auth/libraries/Auth.php @@ -0,0 +1,93 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +/** + * Implement the Authentication. + * + * This code was heavily influenced by code from: + * - http://code.google.com/p/kohana-mptt/ + * - http://code.google.com/p/kohana-mptt/wiki/Documentation + * - http://code.google.com/p/s7ncms/source/browse/trunk/modules/s7ncms/libraries/ORM_MPTT.php + * + * It was extended to allow configurable drivers + */ +class Auth_Core implements Auth_Driver { + + // Session singleton + private static $instance; + + // Configuration and driver + protected $_config; + protected $_driver; + + /** + * Singleton instance of Session. + */ + public static function instance($config = array()) { + if (self::$instance == NULL) { + // Create a new instance + self::$instance = new Auth($config); + } + + return self::$instance; + } + + /** + * On first instance creation, sets up the driver. + */ + protected function __construct($config = array()) { + // Load config + $config += Kohana::config('auth'); + + // Set the driver class name + $driver = "Auth_{$config['driver']}_Driver"; + if (!Kohana::auto_load($driver)) { + // @todo change to gallery specific exceptions + throw new Kohana_Exception("Specified Driver: '{$config['driver']}' has not been defined."); + } + + // Load the driver + $driver = new $driver(); + + if (!($driver instanceof Auth_Driver)) { + // @todo change to gallery specific exceptions + throw new Kohana_Exception( + "Specified Driver: '{$config['driver']}' has not implemented 'Auth_Driver'."); + } + + $this->_driver = $driver; + $this->_config = $config; + + Kohana::log('debug', 'Auth Library initialized'); + } + + /** + * @see Auth_Driver::set_user_password + */ + public function set_user_password($user_id, $password) { + return $this->_driver->set_user_password($user_id, $password); + } + + /** + * @see Auth_Driver::is_valid_password + */ + public function is_valid_password($user_id, $password) { + return $this->_driver->is_valid_password($user_id, $password); + } +} diff --git a/modules/auth/libraries/drivers/Auth.php b/modules/auth/libraries/drivers/Auth.php new file mode 100644 index 00000000..6a6d31b6 --- /dev/null +++ b/modules/auth/libraries/drivers/Auth.php @@ -0,0 +1,37 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +interface Auth_Driver { + /** + * Set the password for the specified user + * + * @param int Gallery User id + * @param string + */ + public function set_user_password($user_id, $password); + + /** + * Validates a user id password combination. + * + * @param int user_id + * @param string password + * @return boolean + */ + public function is_valid_password($user_id, $password); +}
\ No newline at end of file diff --git a/modules/auth/libraries/drivers/Auth/Basic.php b/modules/auth/libraries/drivers/Auth/Basic.php new file mode 100644 index 00000000..2621812a --- /dev/null +++ b/modules/auth/libraries/drivers/Auth/Basic.php @@ -0,0 +1,146 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +class Auth_Basic_Driver implements Auth_Driver { + // Configuration + protected $_config; + + /** + * Instantiate the Driver and initialize it's configuration. + */ + public function __construct($config = array()) { + // Load config + $config += Kohana::config('basic_auth'); + + // Clean up the salt pattern and split it into an array + $config['salt_pattern'] = preg_split('/,\s*/', $config['salt_pattern']); + $this->_config = $config; + + Kohana::log('debug', 'Auth_Basic_Driver Library initialized'); + } + + /** + * @see Auth_Driver::set_user_password + * + * @param int $user_id + * @param string $password + * @return void + */ + public function set_user_password($user_id, $password_text) { + $password = ORM::factory("password")->where('user_id', $user_id)->find(); + $password->password = $this->_hash_password($password_text); + if (empty($password->user_id)) { + $password->user_id = $user_id; + } + $password->save(); + } + + /** + * Validates a user id password combination. + * + * @param int user_id + * @param string password + * @return boolean + */ + public function is_valid_password($user_id, $password_text) { + $password = ORM::factory("password") + ->where('user_id', $user_id) + ->find(); + if ($password->loaded != true) { + return false; + } + + // Get the salt from the stored password + $salt = $this->_find_salt($password->password); + $hashed = $this->_hash_password($password_text, $salt); + + return $hashed === $password->password; + } + + /** + * Creates a hashed password from a plaintext password, inserting salt + * based on the configured salt pattern. + * + * @param string plaintext password + * @return string hashed password string + */ + private function _hash_password($password, $salt = FALSE) { + if ($salt === FALSE) { + // Create a salt seed, same length as the number of offsets in the pattern + $salt = substr($this->_hash(uniqid(NULL, TRUE)), 0, count($this->_config['salt_pattern'])); + } + + // Password hash that the salt will be inserted into + $hash = $this->_hash($salt . $password); + + // Change salt to an array + $salt = str_split($salt, 1); + + // Returned password + $password = ''; + + // Used to calculate the length of splits + $last_offset = 0; + + foreach ($this->_config['salt_pattern'] as $offset) { + // Split a new part of the hash off + $part = substr($hash, 0, $offset - $last_offset); + + // Cut the current part out of the hash + $hash = substr($hash, $offset - $last_offset); + + // Add the part to the password, appending the salt character + $password .= $part . array_shift($salt); + + // Set the last offset to the current offset + $last_offset = $offset; + } + + // Return the password, with the remaining hash appended + return $password . $hash; + } + + /** + * Perform a hash, using the configured method. + * + * @param string string to hash + * @return string + */ + private function _hash($str) { + return hash($this->_config['hash_method'], $str); + } + + /** + * Finds the salt from a password, based on the configured salt pattern. + * + * @param string hashed password + * @return string + */ + private function _find_salt($password) { + $salt = ''; + + foreach ($this->_config['salt_pattern'] as $i => $offset) { + // Find salt characters... take a good long look.. + $salt .= substr($password, $offset + $i, 1); + } + + return $salt; + } +} + diff --git a/modules/auth/models/password.php b/modules/auth/models/password.php new file mode 100644 index 00000000..fd1fee58 --- /dev/null +++ b/modules/auth/models/password.php @@ -0,0 +1,22 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +class Password_Model extends ORM { + protected $belongs_to = array("users"); +}
\ No newline at end of file diff --git a/modules/auth/tests/Auth_Installer_Test.php b/modules/auth/tests/Auth_Installer_Test.php new file mode 100644 index 00000000..110131ab --- /dev/null +++ b/modules/auth/tests/Auth_Installer_Test.php @@ -0,0 +1,36 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2008 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * This test case operates under the assumption that core_installer::install() is called by the + * test controller before it starts. + */ +class Auth_Installer_Test extends Unit_Test_Case { + public function install_basic_add_password_test() { + $user = ORM::factory('user')->find(1); + + $auth = Auth::instance(array('driver' => 'Basic')); + + $auth->set_user_password($user->id, "test_password"); + + $this->assert_false($auth->is_valid_password($user->id, "invalid_password")); + $this->assert_true($auth->is_valid_password($user->id, "test_password")); + } +} diff --git a/modules/gallery_unit_test/controllers/test.php b/modules/gallery_unit_test/controllers/test.php index 543d3183..0761dc12 100644 --- a/modules/gallery_unit_test/controllers/test.php +++ b/modules/gallery_unit_test/controllers/test.php @@ -61,6 +61,7 @@ class Test_Controller extends Controller { // We probably don't want to uninstall and reinstall the core every time, but let's start off // this way. Uninstall modules first and core last. Ignore errors during uninstall. try { + auth_installer::uninstall(); user_installer::uninstall(); core_installer::uninstall(); } catch (Exception $e) { @@ -68,6 +69,7 @@ class Test_Controller extends Controller { core_installer::install(); user_installer::install(); + auth_installer::install(); print new Unit_Test(); } |