Make Kanboard compatible with PHP 5.3.3
This commit is contained in:
parent
4b89b90df2
commit
2bdd6a6b35
|
|
@ -65,6 +65,11 @@ Vagrant.configure("2") do |config|
|
|||
m.vm.synced_folder ".", "/var/www/html", owner: "apache", group: "apache"
|
||||
end
|
||||
|
||||
config.vm.define "centos65" do |m|
|
||||
m.vm.box = "chef/centos-6.5"
|
||||
m.vm.synced_folder ".", "/var/www/html", owner: "apache", group: "apache"
|
||||
end
|
||||
|
||||
config.vm.define "freebsd10" do |m|
|
||||
m.vm.box = "chef/freebsd-10.0"
|
||||
m.vm.synced_folder ".", "/usr/local/www/apache24/data", type: "rsync", owner: "www", group: "www"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,227 @@
|
|||
<?php
|
||||
/**
|
||||
* A Compatibility library with PHP 5.5's simplified password hashing API.
|
||||
*
|
||||
* @author Anthony Ferrara <ircmaxell@php.net>
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @copyright 2012 The Authors
|
||||
*/
|
||||
|
||||
if (!defined('PASSWORD_BCRYPT')) {
|
||||
|
||||
define('PASSWORD_BCRYPT', 1);
|
||||
define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
|
||||
|
||||
define('PASSWORD_PREFIX', '$2a$');
|
||||
}
|
||||
else {
|
||||
|
||||
define('PASSWORD_PREFIX', '$2y$');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash the password using the specified algorithm
|
||||
*
|
||||
* @param string $password The password to hash
|
||||
* @param int $algo The algorithm to use (Defined by PASSWORD_* constants)
|
||||
* @param array $options The options for the algorithm to use
|
||||
*
|
||||
* @return string|false The hashed password, or false on error.
|
||||
*/
|
||||
function password_hash($password, $algo, array $options = array()) {
|
||||
if (!function_exists('crypt')) {
|
||||
trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!is_string($password)) {
|
||||
trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!is_int($algo)) {
|
||||
trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
switch ($algo) {
|
||||
case PASSWORD_BCRYPT:
|
||||
// Note that this is a C constant, but not exposed to PHP, so we don't define it here.
|
||||
$cost = 10;
|
||||
if (isset($options['cost'])) {
|
||||
$cost = $options['cost'];
|
||||
if ($cost < 4 || $cost > 31) {
|
||||
trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$required_salt_len = 22;
|
||||
$hash_format = sprintf("%s%02d$", PASSWORD_PREFIX, $cost);
|
||||
break;
|
||||
default:
|
||||
trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (isset($options['salt'])) {
|
||||
switch (gettype($options['salt'])) {
|
||||
case 'NULL':
|
||||
case 'boolean':
|
||||
case 'integer':
|
||||
case 'double':
|
||||
case 'string':
|
||||
$salt = (string) $options['salt'];
|
||||
break;
|
||||
case 'object':
|
||||
if (method_exists($options['salt'], '__tostring')) {
|
||||
$salt = (string) $options['salt'];
|
||||
break;
|
||||
}
|
||||
case 'array':
|
||||
case 'resource':
|
||||
default:
|
||||
trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (strlen($salt) < $required_salt_len) {
|
||||
trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING);
|
||||
return null;
|
||||
} elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
|
||||
$salt = str_replace('+', '.', base64_encode($salt));
|
||||
}
|
||||
} else {
|
||||
$buffer = '';
|
||||
$raw_length = (int) ($required_salt_len * 3 / 4 + 1);
|
||||
$buffer_valid = false;
|
||||
if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
|
||||
$buffer = mcrypt_create_iv($raw_length, MCRYPT_DEV_URANDOM);
|
||||
if ($buffer) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
|
||||
$buffer = openssl_random_pseudo_bytes($raw_length);
|
||||
if ($buffer) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid && is_readable('/dev/urandom')) {
|
||||
$f = fopen('/dev/urandom', 'r');
|
||||
$read = strlen($buffer);
|
||||
while ($read < $raw_length) {
|
||||
$buffer .= fread($f, $raw_length - $read);
|
||||
$read = strlen($buffer);
|
||||
}
|
||||
fclose($f);
|
||||
if ($read >= $raw_length) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid || strlen($buffer) < $raw_length) {
|
||||
$bl = strlen($buffer);
|
||||
for ($i = 0; $i < $raw_length; $i++) {
|
||||
if ($i < $bl) {
|
||||
$buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
|
||||
} else {
|
||||
$buffer .= chr(mt_rand(0, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
$salt = str_replace('+', '.', base64_encode($buffer));
|
||||
|
||||
}
|
||||
$salt = substr($salt, 0, $required_salt_len);
|
||||
|
||||
$hash = $hash_format . $salt;
|
||||
|
||||
$ret = crypt($password, $hash);
|
||||
|
||||
if (!is_string($ret) || strlen($ret) <= 13) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about the password hash. Returns an array of the information
|
||||
* that was used to generate the password hash.
|
||||
*
|
||||
* array(
|
||||
* 'algo' => 1,
|
||||
* 'algoName' => 'bcrypt',
|
||||
* 'options' => array(
|
||||
* 'cost' => 10,
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* @param string $hash The password hash to extract info from
|
||||
*
|
||||
* @return array The array of information about the hash.
|
||||
*/
|
||||
function password_get_info($hash) {
|
||||
$return = array(
|
||||
'algo' => 0,
|
||||
'algoName' => 'unknown',
|
||||
'options' => array(),
|
||||
);
|
||||
if (substr($hash, 0, 4) == PASSWORD_PREFIX && strlen($hash) == 60) {
|
||||
$return['algo'] = PASSWORD_BCRYPT;
|
||||
$return['algoName'] = 'bcrypt';
|
||||
list($cost) = sscanf($hash, PASSWORD_PREFIX."%d$");
|
||||
$return['options']['cost'] = $cost;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the password hash needs to be rehashed according to the options provided
|
||||
*
|
||||
* If the answer is true, after validating the password using password_verify, rehash it.
|
||||
*
|
||||
* @param string $hash The hash to test
|
||||
* @param int $algo The algorithm used for new password hashes
|
||||
* @param array $options The options array passed to password_hash
|
||||
*
|
||||
* @return boolean True if the password needs to be rehashed.
|
||||
*/
|
||||
function password_needs_rehash($hash, $algo, array $options = array()) {
|
||||
$info = password_get_info($hash);
|
||||
if ($info['algo'] != $algo) {
|
||||
return true;
|
||||
}
|
||||
switch ($algo) {
|
||||
case PASSWORD_BCRYPT:
|
||||
$cost = isset($options['cost']) ? $options['cost'] : 10;
|
||||
if ($cost != $info['options']['cost']) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a password against a hash using a timing attack resistant approach
|
||||
*
|
||||
* @param string $password The password to verify
|
||||
* @param string $hash The hash to verify against
|
||||
*
|
||||
* @return boolean If the password matches the hash
|
||||
*/
|
||||
function password_verify($password, $hash) {
|
||||
if (!function_exists('crypt')) {
|
||||
trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
$ret = crypt($password, $hash);
|
||||
if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$status = 0;
|
||||
for ($i = 0; $i < strlen($ret); $i++) {
|
||||
$status |= (ord($ret[$i]) ^ ord($hash[$i]));
|
||||
}
|
||||
|
||||
return $status === 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
// PHP 5.3.3 minimum
|
||||
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
|
||||
die('This software require PHP 5.3.7 minimum');
|
||||
if (version_compare(PHP_VERSION, '5.3.3', '<')) {
|
||||
die('This software require PHP 5.3.3 minimum');
|
||||
}
|
||||
|
||||
// Checks for PHP < 5.4
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"ircmaxell/password-compat": "1.0.3",
|
||||
"fguillot/simple-validator": "0.0.1",
|
||||
"swiftmailer/swiftmailer": "@stable",
|
||||
"fguillot/json-rpc": "0.0.1",
|
||||
|
|
@ -16,7 +15,8 @@
|
|||
"autoload": {
|
||||
"psr-0": {"": "app/"},
|
||||
"files": [
|
||||
"app/functions.php"
|
||||
"app/functions.php",
|
||||
"app/Libs/password.php"
|
||||
]
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "612189500b5effe5179e83afa3d3256c",
|
||||
"hash": "b20bc90f39f04bf9d6828329d56cdc75",
|
||||
"packages": [
|
||||
{
|
||||
"name": "erusev/parsedown",
|
||||
|
|
@ -193,45 +193,6 @@
|
|||
"homepage": "https://github.com/fguillot/simpleLogger",
|
||||
"time": "2015-01-02 03:40:21"
|
||||
},
|
||||
{
|
||||
"name": "ircmaxell/password-compat",
|
||||
"version": "1.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ircmaxell/password_compat.git",
|
||||
"reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/1fc1521b5e9794ea77e4eca30717be9635f1d4f4",
|
||||
"reference": "1fc1521b5e9794ea77e4eca30717be9635f1d4f4",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/password.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Anthony Ferrara",
|
||||
"email": "ircmaxell@ircmaxell.com",
|
||||
"homepage": "http://blog.ircmaxell.com"
|
||||
}
|
||||
],
|
||||
"description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
|
||||
"homepage": "https://github.com/ircmaxell/password_compat",
|
||||
"keywords": [
|
||||
"hashing",
|
||||
"password"
|
||||
],
|
||||
"time": "2013-04-30 19:58:08"
|
||||
},
|
||||
{
|
||||
"name": "lusitanian/oauth",
|
||||
"version": "v0.3.5",
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ rm kanboard-latest.zip
|
|||
Debian 6 (Squeeze)
|
||||
------------------
|
||||
|
||||
**Kanboard >= 1.0.10 require at least PHP 5.3.7 and Debian 6 provide PHP 5.3.3 by default**
|
||||
|
||||
Install Apache and PHP:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -45,14 +45,17 @@ The project [eAccelerator seems dead and not updated since 2012](https://github.
|
|||
We recommend to switch to the last version of PHP because it's bundled with [OPcache](http://php.net/manual/en/intro.opcache.php).
|
||||
|
||||
|
||||
Why the minimum requirement is PHP 5.3.7?
|
||||
Why the minimum requirement is PHP 5.3.3?
|
||||
-----------------------------------------
|
||||
|
||||
Kanboard use the function `password_hash()` to crypt passwords but it's available only for PHP >= 5.5.
|
||||
|
||||
However, there is a backport for [older versions of PHP](https://github.com/ircmaxell/password_compat#requirements).
|
||||
This library require at least PHP 5.3.7 to work correctly.
|
||||
This library require at least PHP 5.3.7 to work correctly.
|
||||
|
||||
Apparently, Centos and Debian backports security patches so PHP 5.3.3 should be ok.
|
||||
|
||||
Kanboard v1.0.10 and v1.0.11 requires at least PHP 5.3.7 but this change has been reverted to be compatible with PHP 5.3.3 with Kanboard >= v1.0.12
|
||||
|
||||
How to test Kanboard with the PHP built-in web server?
|
||||
------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Reference in New Issue