Merge pull request #10642 from owncloud/securityutils
Add some security utilities
This commit is contained in:
commit
373d1c5e9f
2
3rdparty
2
3rdparty
|
@ -1 +1 @@
|
|||
Subproject commit 57245d2a64c99aab8a438f909988e7a4ffef5b23
|
||||
Subproject commit 82d02dd48ad11312bd740c57720dc84b4d66fa8a
|
|
@ -35,6 +35,9 @@ $CONFIG = array(
|
|||
/* Define the salt used to hash the user passwords. All your user passwords are lost if you lose this string. */
|
||||
"passwordsalt" => "",
|
||||
|
||||
/* Secret used by ownCloud for various purposes, e.g. to encrypt data. If you lose this string there will be data corruption. */
|
||||
"secret" => "",
|
||||
|
||||
/* Force use of HTTPS connection (true = use HTTPS) */
|
||||
"forcessl" => false,
|
||||
|
||||
|
|
|
@ -153,7 +153,6 @@ class Controller {
|
|||
'hasMSSQL' => $hasMSSQL,
|
||||
'databases' => $databases,
|
||||
'directory' => $datadir,
|
||||
'secureRNG' => \OC_Util::secureRNGAvailable(),
|
||||
'htaccessWorking' => $htaccessWorking,
|
||||
'vulnerableToNullByte' => $vulnerableToNullByte,
|
||||
'errors' => $errors,
|
||||
|
|
|
@ -27,13 +27,6 @@
|
|||
<?php p($l->t('Please update your PHP installation to use %s securely.', $theme->getName() )); ?></p>
|
||||
</fieldset>
|
||||
<?php endif; ?>
|
||||
<?php if(!$_['secureRNG']): ?>
|
||||
<fieldset class="warning">
|
||||
<legend><strong><?php p($l->t('Security Warning'));?></strong></legend>
|
||||
<p><?php p($l->t('No secure random number generator is available, please enable the PHP OpenSSL extension.'));?><br/>
|
||||
<?php p($l->t('Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account.'));?></p>
|
||||
</fieldset>
|
||||
<?php endif; ?>
|
||||
<?php if(!$_['htaccessWorking']): ?>
|
||||
<fieldset class="warning">
|
||||
<legend><strong><?php p($l->t('Security Warning'));?></strong></legend>
|
||||
|
|
|
@ -71,6 +71,7 @@ class Repair extends BasicEmitter {
|
|||
return array(
|
||||
new \OC\Repair\RepairMimeTypes(),
|
||||
new \OC\Repair\RepairLegacyStorages(\OC::$server->getConfig(), \OC_DB::getConnection()),
|
||||
new \OC\Repair\RepairConfig(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
|
||||
namespace OC\Security;
|
||||
|
||||
use Crypt_AES;
|
||||
use Crypt_Hash;
|
||||
use OCP\Security\ICrypto;
|
||||
use OCP\Security\ISecureRandom;
|
||||
use OCP\Security\StringUtils;
|
||||
use OCP\IConfig;
|
||||
|
||||
/**
|
||||
* Class Crypto provides a high-level encryption layer using AES-CBC. If no key has been provided
|
||||
* it will use the secret defined in config.php as key. Additionally the message will be HMAC'd.
|
||||
*
|
||||
* Usage:
|
||||
* $encryptWithDefaultPassword = \OC::$server->getCrypto()->encrypt('EncryptedText');
|
||||
* $encryptWithCustompassword = \OC::$server->getCrypto()->encrypt('EncryptedText', 'password');
|
||||
*
|
||||
* @package OC\Security
|
||||
*/
|
||||
class Crypto implements ICrypto {
|
||||
/** @var Crypt_AES $cipher */
|
||||
private $cipher;
|
||||
/** @var int */
|
||||
private $ivLength = 16;
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
/** @var ISecureRandom */
|
||||
private $random;
|
||||
|
||||
function __construct(IConfig $config, ISecureRandom $random) {
|
||||
$this->cipher = new Crypt_AES();
|
||||
$this->config = $config;
|
||||
$this->random = $random;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message The message to authenticate
|
||||
* @param string $password Password to use (defaults to `secret` in config.php)
|
||||
* @return string Calculated HMAC
|
||||
*/
|
||||
public function calculateHMAC($message, $password = '') {
|
||||
if($password === '') {
|
||||
$password = $this->config->getSystemValue('secret');
|
||||
}
|
||||
|
||||
// Append an "a" behind the password and hash it to prevent reusing the same password as for encryption
|
||||
$password = hash('sha512', $password . 'a');
|
||||
|
||||
$hash = new Crypt_Hash('sha512');
|
||||
$hash->setKey($password);
|
||||
return $hash->hash($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a value and adds an HMAC (Encrypt-Then-MAC)
|
||||
* @param string $plaintext
|
||||
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken
|
||||
* @return string Authenticated ciphertext
|
||||
*/
|
||||
public function encrypt($plaintext, $password = '') {
|
||||
if($password === '') {
|
||||
$password = $this->config->getSystemValue('secret');
|
||||
}
|
||||
$this->cipher->setPassword($password);
|
||||
|
||||
$iv = $this->random->getLowStrengthGenerator()->generate($this->ivLength);
|
||||
$this->cipher->setIV($iv);
|
||||
|
||||
$ciphertext = bin2hex($this->cipher->encrypt($plaintext));
|
||||
$hmac = bin2hex($this->calculateHMAC($ciphertext.$iv, $password));
|
||||
|
||||
return $ciphertext.'|'.$iv.'|'.$hmac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a value and verifies the HMAC (Encrypt-Then-Mac)
|
||||
* @param string $authenticatedCiphertext
|
||||
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken
|
||||
* @return string plaintext
|
||||
* @throws \Exception If the HMAC does not match
|
||||
*/
|
||||
public function decrypt($authenticatedCiphertext, $password = '') {
|
||||
if($password === '') {
|
||||
$password = $this->config->getSystemValue('secret');
|
||||
}
|
||||
$this->cipher->setPassword($password);
|
||||
|
||||
$parts = explode('|', $authenticatedCiphertext);
|
||||
if(sizeof($parts) !== 3) {
|
||||
throw new \Exception('Authenticated ciphertext could not be decoded.');
|
||||
}
|
||||
|
||||
$ciphertext = hex2bin($parts[0]);
|
||||
$iv = $parts[1];
|
||||
$hmac = hex2bin($parts[2]);
|
||||
|
||||
$this->cipher->setIV($iv);
|
||||
|
||||
if(!StringUtils::equals($this->calculateHMAC($parts[0].$parts[1], $password), $hmac)) {
|
||||
throw new \Exception('HMAC does not match.');
|
||||
}
|
||||
|
||||
return $this->cipher->decrypt($ciphertext);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OC\Security;
|
||||
|
||||
use RandomLib;
|
||||
use Sabre\DAV\Exception;
|
||||
use OCP\Security\ISecureRandom;
|
||||
|
||||
/**
|
||||
* Class SecureRandom provides a layer around RandomLib to generate
|
||||
* secure random strings.
|
||||
*
|
||||
* Usage:
|
||||
* \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(10);
|
||||
*
|
||||
* @package OC\Security
|
||||
*/
|
||||
class SecureRandom implements ISecureRandom {
|
||||
|
||||
/** @var \RandomLib\Factory */
|
||||
var $factory;
|
||||
/** @var \RandomLib\Generator */
|
||||
var $generator;
|
||||
|
||||
function __construct() {
|
||||
$this->factory = new RandomLib\Factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to get a low strength random number generator.
|
||||
*
|
||||
* Low Strength should be used anywhere that random strings are needed
|
||||
* in a non-cryptographical setting. They are not strong enough to be
|
||||
* used as keys or salts. They are however useful for one-time use tokens.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getLowStrengthGenerator() {
|
||||
$this->generator = $this->factory->getLowStrengthGenerator();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to get a medium strength random number generator.
|
||||
*
|
||||
* Medium Strength should be used for most needs of a cryptographic nature.
|
||||
* They are strong enough to be used as keys and salts. However, they do
|
||||
* take some time and resources to generate, so they should not be over-used
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getMediumStrengthGenerator() {
|
||||
$this->generator = $this->factory->getMediumStrengthGenerator();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random string of specified length.
|
||||
* @param string $length The length of the generated string
|
||||
* @param string $characters An optional list of characters to use if no characterlist is
|
||||
* specified 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./
|
||||
* is used.
|
||||
* @return string
|
||||
* @throws \Exception If the generator is not initialized.
|
||||
*/
|
||||
public function generate($length, $characters = '') {
|
||||
if(is_null($this->generator)) {
|
||||
throw new \Exception('Generator is not initialized.');
|
||||
}
|
||||
|
||||
return $this->generator->generateString($length, $characters);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OC\Security;
|
||||
|
||||
class StringUtils {
|
||||
|
||||
/**
|
||||
* Compares whether two strings are equal. To prevent guessing of the string
|
||||
* length this is done by comparing two hashes against each other and afterwards
|
||||
* a comparison of the real string to prevent against the unlikely chance of
|
||||
* collisions.
|
||||
*
|
||||
* Be aware that this function may leak whether the string to compare have a different
|
||||
* length.
|
||||
*
|
||||
* @param string $expected The expected value
|
||||
* @param string $input The input to compare against
|
||||
* @return bool True if the two strings are equal, otherwise false.
|
||||
*/
|
||||
public static function equals($expected, $input) {
|
||||
|
||||
if(function_exists('hash_equals')) {
|
||||
return hash_equals($expected, $input);
|
||||
}
|
||||
|
||||
$randomString = \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(10);
|
||||
|
||||
if(hash('sha512', $expected.$randomString) === hash('sha512', $input.$randomString)) {
|
||||
if($expected === $input) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -10,6 +10,8 @@ use OC\Security\CertificateManager;
|
|||
use OC\DB\ConnectionWrapper;
|
||||
use OC\Files\Node\Root;
|
||||
use OC\Files\View;
|
||||
use OC\Security\Crypto;
|
||||
use OC\Security\SecureRandom;
|
||||
use OCP\IServerContainer;
|
||||
use OCP\ISession;
|
||||
|
||||
|
@ -201,6 +203,12 @@ class Server extends SimpleContainer implements IServerContainer {
|
|||
$this->registerService('Search', function ($c) {
|
||||
return new Search();
|
||||
});
|
||||
$this->registerService('SecureRandom', function($c) {
|
||||
return new SecureRandom();
|
||||
});
|
||||
$this->registerService('Crypto', function($c) {
|
||||
return new Crypto(\OC::$server->getConfig(), \OC::$server->getSecureRandom());
|
||||
});
|
||||
$this->registerService('Db', function ($c) {
|
||||
return new Db();
|
||||
});
|
||||
|
@ -467,6 +475,24 @@ class Server extends SimpleContainer implements IServerContainer {
|
|||
return $this->query('Search');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SecureRandom instance
|
||||
*
|
||||
* @return \OCP\Security\ISecureRandom
|
||||
*/
|
||||
function getSecureRandom() {
|
||||
return $this->query('SecureRandom');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Crypto instance
|
||||
*
|
||||
* @return \OCP\Security\ICrypto
|
||||
*/
|
||||
function getCrypto() {
|
||||
return $this->query('Crypto');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the db facade
|
||||
*
|
||||
|
|
|
@ -67,14 +67,19 @@ class OC_Setup {
|
|||
}
|
||||
|
||||
//generate a random salt that is used to salt the local user passwords
|
||||
$salt = OC_Util::generateRandomBytes(30);
|
||||
OC_Config::setValue('passwordsalt', $salt);
|
||||
$salt = \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(30);
|
||||
\OC::$server->getConfig()->setSystemValue('passwordsalt', $salt);
|
||||
|
||||
// generate a secret
|
||||
$secret = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(48);
|
||||
\OC::$server->getConfig()->setSystemValue('secret', $secret);
|
||||
|
||||
//write the config file
|
||||
OC_Config::setValue('trusted_domains', $trustedDomains);
|
||||
OC_Config::setValue('datadirectory', $datadir);
|
||||
OC_Config::setValue('dbtype', $dbtype);
|
||||
OC_Config::setValue('version', implode('.', OC_Util::getVersion()));
|
||||
\OC::$server->getConfig()->setSystemValue('trusted_domains', $trustedDomains);
|
||||
\OC::$server->getConfig()->setSystemValue('datadirectory', $datadir);
|
||||
\OC::$server->getConfig()->setSystemValue('dbtype', $dbtype);
|
||||
\OC::$server->getConfig()->setSystemValue('version', implode('.', OC_Util::getVersion()));
|
||||
|
||||
try {
|
||||
$dbSetup->initialize($options);
|
||||
$dbSetup->setupDatabase($username);
|
||||
|
|
|
@ -905,7 +905,7 @@ class OC_Util {
|
|||
$id = OC_Config::getValue('instanceid', null);
|
||||
if (is_null($id)) {
|
||||
// We need to guarantee at least one letter in instanceid so it can be used as the session_name
|
||||
$id = 'oc' . self::generateRandomBytes(10);
|
||||
$id = 'oc' . \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(10);
|
||||
OC_Config::$object->setValue('instanceid', $id);
|
||||
}
|
||||
return $id;
|
||||
|
@ -1208,54 +1208,20 @@ class OC_Util {
|
|||
*
|
||||
* @param int $length of the random string
|
||||
* @return string
|
||||
* @throws Exception when no secure RNG source is available
|
||||
* Please also update secureRNGAvailable if you change something here
|
||||
* @deprecated Use \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate($length); instead
|
||||
*/
|
||||
public static function generateRandomBytes($length = 30) {
|
||||
// Try to use openssl_random_pseudo_bytes
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
$pseudoByte = bin2hex(openssl_random_pseudo_bytes($length, $strong));
|
||||
if ($strong == true) {
|
||||
return substr($pseudoByte, 0, $length); // Truncate it to match the length
|
||||
}
|
||||
}
|
||||
|
||||
// Try to use /dev/urandom
|
||||
if (!self::runningOnWindows()) {
|
||||
$fp = @file_get_contents('/dev/urandom', false, null, 0, $length);
|
||||
if ($fp !== false) {
|
||||
$string = substr(bin2hex($fp), 0, $length);
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
// No random numbers are better then bad random numbers
|
||||
throw new \Exception('No secure random number generator available, please install the php-openssl extension');
|
||||
return \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a secure random number generator is available
|
||||
*
|
||||
* @return bool
|
||||
* @return true
|
||||
* @deprecated Function will be removed in the future and does only return true.
|
||||
*/
|
||||
public static function secureRNGAvailable() {
|
||||
// Check openssl_random_pseudo_bytes
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
openssl_random_pseudo_bytes(1, $strong);
|
||||
if ($strong == true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check /dev/urandom
|
||||
if (!self::runningOnWindows()) {
|
||||
$fp = @file_get_contents('/dev/urandom', false, null, 0, 1);
|
||||
if ($fp !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCP\Security;
|
||||
|
||||
/**
|
||||
* Class Crypto provides a high-level encryption layer using AES-CBC. If no key has been provided
|
||||
* it will use the secret defined in config.php as key. Additionally the message will be HMAC'd.
|
||||
*
|
||||
* Usage:
|
||||
* $encryptWithDefaultPassword = \OC::$server->getCrypto()->encrypt('EncryptedText');
|
||||
* $encryptWithCustomPassword = \OC::$server->getCrypto()->encrypt('EncryptedText', 'password');
|
||||
*
|
||||
* @package OCP\Security
|
||||
*/
|
||||
interface ICrypto {
|
||||
|
||||
/**
|
||||
* @param string $message The message to authenticate
|
||||
* @param string $password Password to use (defaults to `secret` in config.php)
|
||||
* @return string Calculated HMAC
|
||||
*/
|
||||
public function calculateHMAC($message, $password = '');
|
||||
|
||||
/**
|
||||
* Encrypts a value and adds an HMAC (Encrypt-Then-MAC)
|
||||
* @param string $plaintext
|
||||
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken
|
||||
* @return string Authenticated ciphertext
|
||||
*/
|
||||
public function encrypt($plaintext, $password = '');
|
||||
|
||||
/**
|
||||
* Decrypts a value and verifies the HMAC (Encrypt-Then-Mac)
|
||||
* @param string $authenticatedCiphertext
|
||||
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken
|
||||
* @return string plaintext
|
||||
* @throws \Exception If the HMAC does not match
|
||||
*/
|
||||
public function decrypt($authenticatedCiphertext, $password = '');
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCP\Security;
|
||||
|
||||
/**
|
||||
* Class SecureRandom provides a layer around RandomLib to generate
|
||||
* secure random numbers.
|
||||
*
|
||||
* Usage:
|
||||
* $rng = new \OC\Security\SecureRandom();
|
||||
* $randomString = $rng->getMediumStrengthGenerator()->generateString(30);
|
||||
*
|
||||
* @package OCP\Security
|
||||
*/
|
||||
interface ISecureRandom {
|
||||
|
||||
/**
|
||||
* Flags for characters that can be used for <code>generate($length, $characters)</code>
|
||||
*/
|
||||
const CHAR_UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
const CHAR_LOWER = 'abcdefghijklmnopqrstuvwxyz';
|
||||
const CHAR_DIGITS = '0123456789';
|
||||
const CHAR_SYMBOLS = '!\"#$%&\\\'()* +,-./:;<=>?@[\]^_`{|}~';
|
||||
|
||||
/**
|
||||
* Convenience method to get a low strength random number generator.
|
||||
*
|
||||
* Low Strength should be used anywhere that random strings are needed
|
||||
* in a non-cryptographical setting. They are not strong enough to be
|
||||
* used as keys or salts. They are however useful for one-time use tokens.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getLowStrengthGenerator();
|
||||
|
||||
/**
|
||||
* Convenience method to get a medium strength random number generator.
|
||||
*
|
||||
* Medium Strength should be used for most needs of a cryptographic nature.
|
||||
* They are strong enough to be used as keys and salts. However, they do
|
||||
* take some time and resources to generate, so they should not be over-used
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getMediumStrengthGenerator();
|
||||
|
||||
/**
|
||||
* Generate a random string of specified length.
|
||||
* @param string $length The length of the generated string
|
||||
* @param string $characters An optional list of characters to use
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function generate($length, $characters = '');
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
|
||||
namespace OCP\Security;
|
||||
|
||||
class StringUtils {
|
||||
/**
|
||||
* Compares whether two strings are equal. To prevent guessing of the string
|
||||
* length this is done by comparing two hashes against each other and afterwards
|
||||
* a comparison of the real string to prevent against the unlikely chance of
|
||||
* collisions.
|
||||
* @param string $expected The expected value
|
||||
* @param string $input The input to compare against
|
||||
* @return bool True if the two strings are equal, otherwise false.
|
||||
*/
|
||||
public static function equals($expected, $input) {
|
||||
return \OC\Security\StringUtils::equals($expected, $input);
|
||||
}
|
||||
}
|
|
@ -505,6 +505,7 @@ class Util {
|
|||
* Generates a cryptographic secure pseudo-random string
|
||||
* @param int $length of the random string
|
||||
* @return string
|
||||
* @deprecated Use \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate($length); instead
|
||||
*/
|
||||
public static function generateRandomBytes($length = 30) {
|
||||
return \OC_Util::generateRandomBytes($length);
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OC\Repair;
|
||||
|
||||
use OC\Hooks\BasicEmitter;
|
||||
use OC\RepairStep;
|
||||
use Sabre\DAV\Exception;
|
||||
|
||||
class RepairConfig extends BasicEmitter implements RepairStep {
|
||||
|
||||
public function getName() {
|
||||
return 'Repair config';
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the configuration after running an update
|
||||
*/
|
||||
public function run() {
|
||||
$this->addSecret();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a secret to config.php
|
||||
*/
|
||||
private function addSecret() {
|
||||
if(\OC::$server->getConfig()->getSystemValue('secret', null) === null) {
|
||||
$secret = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(48);
|
||||
\OC::$server->getConfig()->setSystemValue('secret', $secret);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
use \OC\Security\Crypto;
|
||||
|
||||
class CryptoTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function defaultEncryptionProvider()
|
||||
{
|
||||
return array(
|
||||
array('Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'),
|
||||
array(''),
|
||||
array('我看这本书。 我看這本書')
|
||||
);
|
||||
}
|
||||
|
||||
/** @var Crypto */
|
||||
protected $crypto;
|
||||
|
||||
protected function setUp() {
|
||||
$this->crypto = new Crypto(\OC::$server->getConfig(), \OC::$server->getSecureRandom());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider defaultEncryptionProvider
|
||||
*/
|
||||
function testDefaultEncrypt($stringToEncrypt) {
|
||||
$ciphertext = $this->crypto->encrypt($stringToEncrypt);
|
||||
$this->assertEquals($stringToEncrypt, $this->crypto->decrypt($ciphertext));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage HMAC does not match.
|
||||
*/
|
||||
function testWrongPassword() {
|
||||
$stringToEncrypt = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.';
|
||||
$ciphertext = $this->crypto->encrypt($stringToEncrypt);
|
||||
$this->crypto->decrypt($ciphertext, 'A wrong password!');
|
||||
}
|
||||
|
||||
function testLaterDecryption() {
|
||||
$stringToEncrypt = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.';
|
||||
$encryptedString = '44a35023cca2e7a6125e06c29fc4b2ad9d8a33d0873a8b45b0de4ef9284f260c6c46bf25dc62120644c59b8bafe4281ddc47a70c35ae6c29ef7a63d79eefacc297e60b13042ac582733598d0a6b4de37311556bb5c480fd2633de4e6ebafa868c2d1e2d80a5d24f9660360dba4d6e0c8|lhrFgK0zd9U160Wo|a75e57ab701f9124e1113543fd1dc596f21e20d456a0d1e813d5a8aaec9adcb11213788e96598b67fe9486a9f0b99642c18296d0175db44b1ae426e4e91080ee';
|
||||
$this->assertEquals($stringToEncrypt, $this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage HMAC does not match.
|
||||
*/
|
||||
function testWrongIV() {
|
||||
$encryptedString = '560f5436ba864b9f12f7f7ca6d41c327554a6f2c0a160a03316b202af07c65163274993f3a46e7547c07ba89304f00594a2f3bd99f83859097c58049c39d0d4ade10e0de914ff0604961e7c849d0271ed6c0b23f984ba16e7d033e3305fb0910e7b6a2a65c988d17dbee71d8f953684d|d2kdFUspVjC0o0sr|1a5feacf87eaa6869a6abdfba9a296e7bbad45b6ad89f7dce67cdc98e2da5dc4379cc672cc655e52bbf19599bf59482fbea13a73937697fa656bf10f3fc4f1aa';
|
||||
$this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage Authenticated ciphertext could not be decoded.
|
||||
*/
|
||||
function testWrongParameters() {
|
||||
$encryptedString = '1|2';
|
||||
$this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
use \OC\Security\SecureRandom;
|
||||
|
||||
class SecureRandomTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function stringGenerationProvider() {
|
||||
return array(
|
||||
array(0, 0),
|
||||
array(1, 1),
|
||||
array(128, 128),
|
||||
array(256, 256),
|
||||
array(1024, 1024),
|
||||
array(2048, 2048),
|
||||
array(64000, 64000),
|
||||
);
|
||||
}
|
||||
|
||||
public static function charCombinations() {
|
||||
return array(
|
||||
array('CHAR_LOWER', '[a-z]'),
|
||||
array('CHAR_UPPER', '[A-Z]'),
|
||||
array('CHAR_DIGITS', '[0-9]'),
|
||||
);
|
||||
}
|
||||
|
||||
/** @var SecureRandom */
|
||||
protected $rng;
|
||||
|
||||
protected function setUp() {
|
||||
$this->rng = new \OC\Security\SecureRandom();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider stringGenerationProvider
|
||||
*/
|
||||
function testGetLowStrengthGeneratorLength($length, $expectedLength) {
|
||||
$generator = $this->rng->getLowStrengthGenerator();
|
||||
|
||||
$this->assertEquals($expectedLength, strlen($generator->generate($length)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider stringGenerationProvider
|
||||
*/
|
||||
function testMediumLowStrengthGeneratorLength($length, $expectedLength) {
|
||||
$generator = $this->rng->getMediumStrengthGenerator();
|
||||
|
||||
$this->assertEquals($expectedLength, strlen($generator->generate($length)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage Generator is not initialized
|
||||
*/
|
||||
function testUninitializedGenerate() {
|
||||
$this->rng->generate(30);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider charCombinations
|
||||
*/
|
||||
public function testScheme($charName, $chars) {
|
||||
$generator = $this->rng->getMediumStrengthGenerator();
|
||||
$scheme = constant('OCP\Security\ISecureRandom::' . $charName);
|
||||
$randomString = $generator->generate(100, $scheme);
|
||||
$matchesRegex = preg_match('/^'.$chars.'+$/', $randomString);
|
||||
$this->assertSame(1, $matchesRegex);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
use \OC\Security\StringUtils;
|
||||
|
||||
class StringUtilsTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function dataProvider()
|
||||
{
|
||||
return array(
|
||||
array('Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.', 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'),
|
||||
array('', ''),
|
||||
array('我看这本书。 我看這本書', '我看这本书。 我看這本書'),
|
||||
array('GpKY9fSnWNJbES99zVGvA', 'GpKY9fSnWNJbES99zVGvA')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProvider
|
||||
*/
|
||||
function testWrongEquals($string) {
|
||||
$this->assertFalse(StringUtils::equals($string, 'A Completely Wrong String'));
|
||||
$this->assertFalse(StringUtils::equals($string, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProvider
|
||||
*/
|
||||
function testTrueEquals($string, $expected) {
|
||||
$this->assertTrue(StringUtils::equals($string, $expected));
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades
|
||||
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
|
||||
// when updating major/minor version number.
|
||||
$OC_Version=array(7, 8, 0, 0);
|
||||
$OC_Version=array(7, 8, 1, 0);
|
||||
|
||||
// The human readable string
|
||||
$OC_VersionString='8.0 pre alpha';
|
||||
|
|
Loading…
Reference in New Issue