diff --git a/application/bootstrap.php b/application/bootstrap.php
index 0f4adad..f93f414 100644
--- a/application/bootstrap.php
+++ b/application/bootstrap.php
@@ -1,6 +1,20 @@
"
+ */
+if (isset($_SERVER['KOHANA_ENV']))
+{
+ Kohana::$environment = constant('Kohana::'.strtoupper($_SERVER['KOHANA_ENV']));
+}
/**
* Initialize Kohana, setting the default options.
@@ -57,27 +87,33 @@ Kohana::init(array(
/**
* Attach the file write to logging. Multiple writers are supported.
*/
-Kohana::$log->attach(new Kohana_Log_File(APPPATH.'logs'));
+Kohana::$log->attach(new Log_File(APPPATH.'logs'));
/**
* Attach a file reader to config. Multiple readers are supported.
*/
-Kohana::$config->attach(new Kohana_Config_File);
+Kohana::$config->attach(new Config_File);
/**
* Enable modules. Modules are referenced by a relative or absolute path.
*/
Kohana::modules(array(
- 'auth' => MODPATH.'auth', // Basic authentication
- // 'cache' => MODPATH.'cache', // Caching with multiple backends
- // 'codebench' => MODPATH.'codebench', // Benchmarking tool
- 'database' => MODPATH.'database', // Database access
- // 'image' => MODPATH.'image', // Image manipulation
- 'orm' => MODPATH.'orm', // Object Relationship Mapping
- // 'oauth' => MODPATH.'oauth', // OAuth authentication
- // 'pagination' => MODPATH.'pagination', // Paging of results
- // 'unittest' => MODPATH.'unittest', // Unit testing
- 'userguide' => MODPATH.'userguide', // User guide and API documentation
+ 'auth' => SMDPATH.'auth', // Basic authentication
+ 'cache' => SMDPATH.'cache', // Caching with multiple backends
+ // 'codebench' => SMDPATH.'codebench', // Benchmarking tool
+ 'database' => SMDPATH.'database', // Database access
+ // 'image' => SMDPATH.'image', // Image manipulation
+ 'orm' => SMDPATH.'orm', // Object Relationship Mapping
+ // 'unittest' => SMDPATH.'unittest', // Unit testing
+ // 'userguide' => SMDPATH.'userguide', // User guide and API documentation
+ ));
+
+/**
+ * Enable specalised interfaces
+ */
+Route::set('sections', '
PECL HTTP Enabled | + +Pass | + +Kohana can use the http extension for the Request_Client_External class. | + +|
---|---|---|---|
cURL Enabled | Pass | -Kohana requires cURL for the Remote class. | +Kohana can use the cURL extension for the Request_Client_External class. |
Kohana requires GD v2 for the Image class. | |||
MySQL Enabled | + +Pass | + +Kohana can use the MySQL extension to support MySQL databases. | + +|
PDO Enabled | diff --git a/includes/kohana/modules/auth/README.md b/includes/kohana/modules/auth/README.md new file mode 100644 index 0000000..27ac9cd --- /dev/null +++ b/includes/kohana/modules/auth/README.md @@ -0,0 +1,13 @@ +New Age Auth +--- + +I've forked the main Auth module because there were some fundamental flaws with it: + + 1. It's trivial to [bruteforce](http://dev.kohanaframework.org/issues/3163) publicly hidden salt hashes. + - I've fixed this by switching the password hashing algorithm to the more secure secret-key based hash_hmac method. + 2. ORM drivers were included. + - I've fixed this by simply removing them. They cause confusion with new users because they think that Auth requires ORM. The only driver currently provided by default is the file driver. + 3. Auth::get_user()'s api is inconsistent because it returns different data types. + - I've fixed this by returning an empty user model by default. You can override what gets returned (if you've changed your user model class name for instance) by overloading the get_user() method in your application. + +These changes should be merged into the mainline branch eventually, but they completely break the API, so likely won't be done until 3.1. \ No newline at end of file diff --git a/includes/kohana/modules/auth/classes/kohana/auth.php b/includes/kohana/modules/auth/classes/kohana/auth.php index 51128f6..c5030e8 100644 --- a/includes/kohana/modules/auth/classes/kohana/auth.php +++ b/includes/kohana/modules/auth/classes/kohana/auth.php @@ -27,7 +27,7 @@ abstract class Kohana_Auth { if ( ! $type = $config->get('driver')) { - $type = 'ORM'; + $type = 'file'; } // Set the session class name @@ -40,16 +40,6 @@ abstract class Kohana_Auth { return Auth::$_instance; } - /** - * Create an instance of Auth. - * - * @return Auth - */ - public static function factory($config = array()) - { - return new Auth($config); - } - protected $_session; protected $_config; @@ -61,9 +51,6 @@ abstract class Kohana_Auth { */ public function __construct($config = array()) { - // Clean up the salt pattern and split it into an array - $config['salt_pattern'] = preg_split('/,\s*/', Kohana::config('auth')->get('salt_pattern')); - // Save the config in the object $this->_config = $config; @@ -78,13 +65,13 @@ abstract class Kohana_Auth { /** * Gets the currently logged in user from the session. - * Returns FALSE if no user is currently logged in. + * Returns NULL if no user is currently logged in. * * @return mixed */ - public function get_user() + public function get_user($default = NULL) { - return $this->_session->get($this->_config['session_key'], FALSE); + return $this->_session->get($this->_config['session_key'], $default); } /** @@ -102,11 +89,8 @@ abstract class Kohana_Auth { if (is_string($password)) { - // Get the salt from the stored password - $salt = $this->find_salt($this->password($username)); - - // Create a hashed password using the salt from the stored password - $password = $this->hash_password($password, $salt); + // Create a hashed password + $password = $this->hash($password); } return $this->_login($username, $password, $remember); @@ -141,90 +125,40 @@ abstract class Kohana_Auth { /** * Check if there is an active session. Optionally allows checking for a - * specific role. + * specific role. * * @param string role name * @return mixed */ public function logged_in($role = NULL) { - return FALSE !== $this->get_user(); + return ($this->get_user() !== NULL); } /** - * Creates a hashed password from a plaintext password, inserting salt - * based on the configured salt pattern. + * Creates a hashed hmac password from a plaintext password. This + * method is deprecated, [Auth::hash] should be used instead. * + * @deprecated * @param string plaintext password - * @return string hashed password string */ - public function hash_password($password, $salt = FALSE) + public function hash_password($password) { - 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; + return $this->hash($password); } /** - * Perform a hash, using the configured method. + * Perform a hmac hash, using the configured method. * * @param string string to hash * @return string */ public function hash($str) { - return hash($this->_config['hash_method'], $str); - } + if ( ! $this->_config['hash_key']) + throw new Kohana_Exception('A valid hash key must be set in your auth config.'); - /** - * Finds the salt from a password, based on the configured salt pattern. - * - * @param string hashed password - * @return string - */ - public 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; + return hash_hmac($this->_config['hash_method'], $str, $this->_config['hash_key']); } protected function complete_login($user) @@ -238,4 +172,4 @@ abstract class Kohana_Auth { return TRUE; } -} // End Auth \ No newline at end of file +} // End Auth diff --git a/includes/kohana/modules/auth/classes/model/auth/role.php b/includes/kohana/modules/auth/classes/model/auth/role.php deleted file mode 100644 index 565c4f0..0000000 --- a/includes/kohana/modules/auth/classes/model/auth/role.php +++ /dev/null @@ -1,27 +0,0 @@ - array('through' => 'roles_users')); - - // Validation rules - protected $_rules = array( - 'name' => array( - 'not_empty' => NULL, - 'min_length' => array(4), - 'max_length' => array(32), - ), - 'description' => array( - 'max_length' => array(255), - ), - ); - -} // End Auth Role Model \ No newline at end of file diff --git a/includes/kohana/modules/auth/classes/model/auth/user.php b/includes/kohana/modules/auth/classes/model/auth/user.php deleted file mode 100644 index 35a512d..0000000 --- a/includes/kohana/modules/auth/classes/model/auth/user.php +++ /dev/null @@ -1,244 +0,0 @@ - array('model' => 'user_token'), - 'roles' => array('model' => 'role', 'through' => 'roles_users'), - ); - - // Validation rules - protected $_rules = array( - 'username' => array( - 'not_empty' => NULL, - 'min_length' => array(4), - 'max_length' => array(32), - 'regex' => array('/^[-\pL\pN_.]++$/uD'), - ), - 'password' => array( - 'not_empty' => NULL, - 'min_length' => array(5), - 'max_length' => array(42), - ), - 'password_confirm' => array( - 'matches' => array('password'), - ), - 'email' => array( - 'not_empty' => NULL, - 'min_length' => array(4), - 'max_length' => array(127), - 'email' => NULL, - ), - ); - - // Validation callbacks - protected $_callbacks = array( - 'username' => array('username_available'), - 'email' => array('email_available'), - ); - - // Field labels - protected $_labels = array( - 'username' => 'username', - 'email' => 'email address', - 'password' => 'password', - 'password_confirm' => 'password confirmation', - ); - - // Columns to ignore - protected $_ignored_columns = array('password_confirm'); - - /** - * Validates login information from an array, and optionally redirects - * after a successful login. - * - * @param array values to check - * @param string URI or URL to redirect to - * @return boolean - */ - public function login(array & $array, $redirect = FALSE) - { - $fieldname = $this->unique_key($array['username']); - $array = Validate::factory($array) - ->label('username', $this->_labels[$fieldname]) - ->label('password', $this->_labels['password']) - ->filter(TRUE, 'trim') - ->rules('username', $this->_rules[$fieldname]) - ->rules('password', $this->_rules['password']); - - // Get the remember login option - $remember = isset($array['remember']); - - // Login starts out invalid - $status = FALSE; - - if ($array->check()) - { - // Attempt to load the user - $this->where($fieldname, '=', $array['username'])->find(); - - if ($this->loaded() AND Auth::instance()->login($this, $array['password'], $remember)) - { - if (is_string($redirect)) - { - // Redirect after a successful login - Request::instance()->redirect($redirect); - } - - // Login is successful - $status = TRUE; - } - else - { - $array->error('username', 'invalid'); - } - } - - return $status; - } - - /** - * Validates an array for a matching password and password_confirm field, - * and optionally redirects after a successful save. - * - * @param array values to check - * @param string URI or URL to redirect to - * @return boolean - */ - public function change_password(array & $array, $redirect = FALSE) - { - $array = Validate::factory($array) - ->label('password', $this->_labels['password']) - ->label('password_confirm', $this->_labels['password_confirm']) - ->filter(TRUE, 'trim') - ->rules('password', $this->_rules['password']) - ->rules('password_confirm', $this->_rules['password_confirm']); - - if ($status = $array->check()) - { - // Change the password - $this->password = $array['password']; - - if ($status = $this->save() AND is_string($redirect)) - { - // Redirect to the success page - Request::instance()->redirect($redirect); - } - } - - return $status; - } - - /** - * Complete the login for a user by incrementing the logins and saving login timestamp - * - * @return void - */ - public function complete_login() - { - if ( ! $this->_loaded) - { - // nothing to do - return; - } - - // Update the number of logins - $this->logins = new Database_Expression('logins + 1'); - - // Set the last login date - $this->last_login = time(); - - // Save the user - $this->save(); - } - - /** - * Does the reverse of unique_key_exists() by triggering error if username exists. - * Validation callback. - * - * @param Validate Validate object - * @param string field name - * @return void - */ - public function username_available(Validate $array, $field) - { - if ($this->unique_key_exists($array[$field], 'username')) - { - $array->error($field, 'username_available', array($array[$field])); - } - } - - /** - * Does the reverse of unique_key_exists() by triggering error if email exists. - * Validation callback. - * - * @param Validate Validate object - * @param string field name - * @return void - */ - public function email_available(Validate $array, $field) - { - if ($this->unique_key_exists($array[$field], 'email')) - { - $array->error($field, 'email_available', array($array[$field])); - } - } - - /** - * Tests if a unique key value exists in the database. - * - * @param mixed the value to test - * @param string field name - * @return boolean - */ - public function unique_key_exists($value, $field = NULL) - { - if ($field === NULL) - { - // Automatically determine field by looking at the value - $field = $this->unique_key($value); - } - - return (bool) DB::select(array('COUNT("*")', 'total_count')) - ->from($this->_table_name) - ->where($field, '=', $value) - ->where($this->_primary_key, '!=', $this->pk()) - ->execute($this->_db) - ->get('total_count'); - } - - /** - * Allows a model use both email and username as unique identifiers for login - * - * @param string unique value - * @return string field name - */ - public function unique_key($value) - { - return Validate::email($value) ? 'email' : 'username'; - } - - /** - * Saves the current object. Will hash password if it was changed. - * - * @return ORM - */ - public function save() - { - if (array_key_exists('password', $this->_changed)) - { - $this->_object['password'] = Auth::instance()->hash_password($this->_object['password']); - } - - return parent::save(); - } - -} // End Auth User Model \ No newline at end of file diff --git a/includes/kohana/modules/auth/config/auth.php b/includes/kohana/modules/auth/config/auth.php index c009819..0d80208 100644 --- a/includes/kohana/modules/auth/config/auth.php +++ b/includes/kohana/modules/auth/config/auth.php @@ -2,17 +2,15 @@ return array( - 'driver' => 'ORM', - 'hash_method' => 'sha1', - 'salt_pattern' => '1, 3, 5, 9, 14, 15, 20, 21, 28, 30', - 'lifetime' => 1209600, - 'session_key' => 'auth_user', - 'autologin_key' => 'auth_autologin', - 'forced_key' => 'auth_forced', + 'driver' => 'file', + 'hash_method' => 'sha256', + 'hash_key' => NULL, + 'lifetime' => 1209600, + 'session_key' => 'auth_user', // Username/password combinations for the Auth File driver 'users' => array( // 'admin' => 'b3154acf3a344170077d11bdb5fff31532f679a1919e716a02', ), -); \ No newline at end of file +); diff --git a/includes/kohana/modules/auth/config/userguide.php b/includes/kohana/modules/auth/config/userguide.php deleted file mode 100644 index b5606e8..0000000 --- a/includes/kohana/modules/auth/config/userguide.php +++ /dev/null @@ -1,23 +0,0 @@ - array( - - // This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename' - 'auth' => array( - - // Whether this modules userguide pages should be shown - 'enabled' => TRUE, - - // The name that should show up on the userguide index page - 'name' => 'Auth', - - // A short description of this module, shown on the index page - 'description' => 'User authentication and authorization.', - - // Copyright message, shown in the footer for this module - 'copyright' => '© 2008–2010 Kohana Team', - ) - ) -); \ No newline at end of file diff --git a/includes/kohana/modules/cache/classes/kohana/cache.php b/includes/kohana/modules/cache/classes/kohana/cache.php index 5c9ac4a..cdef449 100644 --- a/includes/kohana/modules/cache/classes/kohana/cache.php +++ b/includes/kohana/modules/cache/classes/kohana/cache.php @@ -138,7 +138,7 @@ abstract class Kohana_Cache { } /** - * @var Kohana_Config + * @var Config */ protected $_config; diff --git a/includes/kohana/modules/cache/classes/kohana/cache/apc.php b/includes/kohana/modules/cache/classes/kohana/cache/apc.php index 64ffe82..78765fe 100644 --- a/includes/kohana/modules/cache/classes/kohana/cache/apc.php +++ b/includes/kohana/modules/cache/classes/kohana/cache/apc.php @@ -71,7 +71,9 @@ class Kohana_Cache_Apc extends Cache { */ public function get($id, $default = NULL) { - return (($data = apc_fetch($this->_sanitize_id($id))) === FALSE) ? $default : $data; + $data = apc_fetch($this->_sanitize_id($id), $success); + + return $success ? $data : $default; } /** diff --git a/includes/kohana/modules/cache/classes/kohana/cache/file.php b/includes/kohana/modules/cache/classes/kohana/cache/file.php index 096ba36..0ace205 100644 --- a/includes/kohana/modules/cache/classes/kohana/cache/file.php +++ b/includes/kohana/modules/cache/classes/kohana/cache/file.php @@ -373,7 +373,7 @@ class Kohana_Cache_File extends Cache implements Kohana_Cache_GarbageCollect { $name = $files->getFilename(); // If the name is not a dot - if ($name != '.' and $name != '..') + if ($name != '.' AND $name != '..' AND substr($file->getFilename(), 0, 1) == '.') { // Create new file resource $fp = new SplFileInfo($files->getRealPath()); diff --git a/includes/kohana/modules/codebench/classes/bench/datespan.php b/includes/kohana/modules/codebench/classes/bench/datespan.php index 6ea1f50..ff35479 100644 --- a/includes/kohana/modules/codebench/classes/bench/datespan.php +++ b/includes/kohana/modules/codebench/classes/bench/datespan.php @@ -29,7 +29,7 @@ class Bench_DateSpan extends Codebench { public static function bench_span_original($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds') { // Array with the output formats - $output = preg_split('/[^a-z]+/', strtolower((string) $output)); + $output = preg_split('/[^a-z]+/', strtolower( (string) $output)); // Invalid output if (empty($output)) @@ -116,7 +116,7 @@ class Bench_DateSpan extends Codebench { public static function bench_span_use_array($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds') { // Array with the output formats - $output = preg_split('/[^a-z]+/', strtolower((string) $output)); + $output = preg_split('/[^a-z]+/', strtolower( (string) $output)); // Invalid output if (empty($output)) diff --git a/includes/kohana/modules/codebench/classes/controller/codebench.php b/includes/kohana/modules/codebench/classes/controller/codebench.php index 52e8404..cdd9a70 100644 --- a/includes/kohana/modules/codebench/classes/controller/codebench.php +++ b/includes/kohana/modules/codebench/classes/controller/codebench.php @@ -17,7 +17,9 @@ class Controller_Codebench extends Kohana_Controller_Template { { // Convert submitted class name to URI segment if (isset($_POST['class'])) + { $this->request->redirect('codebench/'.trim($_POST['class'])); + } // Pass the class name on to the view $this->template->class = (string) $class; diff --git a/includes/kohana/modules/codebench/media/guide/codebench/codebench_screenshot1.png b/includes/kohana/modules/codebench/media/guide/codebench/codebench_screenshot1.png old mode 100755 new mode 100644 diff --git a/includes/kohana/modules/codebench/media/guide/codebench/codebench_screenshot2.png b/includes/kohana/modules/codebench/media/guide/codebench/codebench_screenshot2.png old mode 100755 new mode 100644 diff --git a/includes/kohana/modules/codebench/views/codebench.php b/includes/kohana/modules/codebench/views/codebench.php index 1961950..7b6ef2a 100644 --- a/includes/kohana/modules/codebench/views/codebench.php +++ b/includes/kohana/modules/codebench/views/codebench.php @@ -2,7 +2,7 @@ /** * Codebench — A benchmarking module. * - * @package Kohana + * @package Kohana/Codebench * @author Kohana Team * @copyright (c) 2009 Kohana Team * @license http://kohanaphp.com/license.html @@ -14,7 +14,9 @@ -