diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 260478e65..62c8fe313 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -2737,7 +2737,7 @@ class AttributeEncryptedString extends AttributeString const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; static $sKey = null; // Encryption key used for all encrypted fields - + static $sLibrary = null; // Encryption library used for all encrypted fields public function __construct($sCode, $aParams) { parent::__construct($sCode, $aParams); @@ -2745,6 +2745,10 @@ class AttributeEncryptedString extends AttributeString { self::$sKey = MetaModel::GetConfig()->GetEncryptionKey(); } + if(self::$sLibrary == null) + { + self::$sLibrary = MetaModel::GetConfig()->GetEncryptionLibrary(); + } } /** * When the attribute definitions are stored in APC cache: @@ -2760,6 +2764,10 @@ class AttributeEncryptedString extends AttributeString { self::$sKey = MetaModel::GetConfig()->GetEncryptionKey(); } + if(self::$sLibrary == null) + { + self::$sLibrary = MetaModel::GetConfig()->GetEncryptionLibrary(); + } } @@ -2788,7 +2796,7 @@ class AttributeEncryptedString extends AttributeString */ public function FromSQLToValue($aCols, $sPrefix = '') { - $oSimpleCrypt = new SimpleCrypt(); + $oSimpleCrypt = new SimpleCrypt(self::$sLibrary); $sValue = $oSimpleCrypt->Decrypt(self::$sKey, $aCols[$sPrefix]); return $sValue; } @@ -2798,7 +2806,7 @@ class AttributeEncryptedString extends AttributeString */ public function GetSQLValues($value) { - $oSimpleCrypt = new SimpleCrypt(); + $oSimpleCrypt = new SimpleCrypt(self::$sLibrary); $encryptedValue = $oSimpleCrypt->Encrypt(self::$sKey, $value); $aValues = array(); diff --git a/core/config.class.inc.php b/core/config.class.inc.php index d7882343a..d0d4590c7 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -37,6 +37,7 @@ define('ACCESS_READONLY', 0); require_once('coreexception.class.inc.php'); require_once('attributedef.class.inc.php'); // For the defines +require_once('simplecrypt.class.inc.php'); class ConfigException extends CoreException { @@ -64,8 +65,8 @@ define('DEFAULT_FAST_RELOAD_INTERVAL', 1 * 60); define('DEFAULT_SECURE_CONNECTION_REQUIRED', false); define('DEFAULT_ALLOWED_LOGIN_TYPES', 'form|basic|external'); define('DEFAULT_EXT_AUTH_VARIABLE', '$_SERVER[\'REMOTE_USER\']'); -define('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random value, later... - +define('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random generated key later (if possible) +define('DEFAULT_ENCRYPTION_LIB', 'Mcrypt'); // We'll define the best encryption available later /** * Config * configuration data (this class cannot not be localized, because it is responsible for loading the dictionaries) @@ -1251,6 +1252,13 @@ class Config */ protected $m_sEncryptionKey; + /** + * @var string Encryption key used for all attributes of type "encrypted string". Can be set to a random value + * unless you want to import a database from another iTop instance, in which case you must use + * the same encryption key in order to properly decode the encrypted fields + */ + protected $m_sEncryptionLibrary; + /** * @var array Additional character sets to be supported by the interactive CSV import * 'iconv_code' => 'display name' @@ -1296,10 +1304,14 @@ class Config $this->m_sDefaultLanguage = 'EN US'; $this->m_sAllowedLoginTypes = DEFAULT_ALLOWED_LOGIN_TYPES; $this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE; - $this->m_sEncryptionKey = DEFAULT_ENCRYPTION_KEY; $this->m_aCharsets = array(); $this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED; + //define default encryption params according to php install + $aEncryptParams = SimpleCrypt::GetNewDefaultParams(); + $this->m_sEncryptionLibrary = isset($aEncryptParams['lib']) ? $aEncryptParams['lib'] : DEFAULT_ENCRYPTION_LIB; + $this->m_sEncryptionKey= isset($aEncryptParams['key']) ? $aEncryptParams['key'] : DEFAULT_ENCRYPTION_KEY; + $this->m_aModuleSettings = array(); if ($bLoadConfig) @@ -1445,7 +1457,8 @@ class Config $this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US'; $this->m_sAllowedLoginTypes = isset($MySettings['allowed_login_types']) ? trim($MySettings['allowed_login_types']) : DEFAULT_ALLOWED_LOGIN_TYPES; $this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE; - $this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : DEFAULT_ENCRYPTION_KEY; + $this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : $this->m_sEncryptionKey; + $this->m_sEncryptionLibrary = isset($MySettings['encryption_library']) ? trim($MySettings['encryption_library']) : $this->m_sEncryptionLibrary; $this->m_aCharsets = isset($MySettings['csv_import_charsets']) ? $MySettings['csv_import_charsets'] : array(); } @@ -1645,6 +1658,11 @@ class Config return $this->m_sEncryptionKey; } + public function GetEncryptionLibrary() + { + return $this->m_sEncryptionLibrary; + } + public function GetAllowedLoginTypes() { return explode('|', $this->m_sAllowedLoginTypes); @@ -1773,6 +1791,7 @@ class Config $aSettings['allowed_login_types'] = $this->m_sAllowedLoginTypes; $aSettings['ext_auth_variable'] = $this->m_sExtAuthVariable; $aSettings['encryption_key'] = $this->m_sEncryptionKey; + $aSettings['encryption_library'] = $this->m_sEncryptionLibrary; $aSettings['csv_import_charsets'] = $this->m_aCharsets; foreach ($this->m_aModuleSettings as $sModule => $aProperties) @@ -1861,6 +1880,7 @@ class Config 'allowed_login_types' => $this->m_sAllowedLoginTypes, 'ext_auth_variable' => $this->m_sExtAuthVariable, 'encryption_key' => $this->m_sEncryptionKey, + 'encryption_library' => $this->m_sEncryptionLibrary, 'csv_import_charsets' => $this->m_aCharsets, ); foreach ($aOtherValues as $sKey => $value) diff --git a/core/simplecrypt.class.inc.php b/core/simplecrypt.class.inc.php index 76e32373f..f3b163519 100644 --- a/core/simplecrypt.class.inc.php +++ b/core/simplecrypt.class.inc.php @@ -43,17 +43,61 @@ class SimpleCrypt { + public static function GetNewDefaultParams() + { + if(function_exists('sodium_crypto_secretbox_open') && function_exists('random_bytes')){ + $sEngineName = 'Sodium'; + } + else if (function_exists('openssl_decrypt')) + { + $sEngineName = 'OpenSSL'; + } + else if(function_exists('mcrypt_module_open')){ + $sEngineName = 'Mcrypt'; + } + else + { + $sEngineName = 'Simple'; + } + $sEngineName = 'SimpleCrypt' . $sEngineName . 'Engine'; + return $sEngineName::GetNewDefaultParams(); + } /** * Constructor - * @param string $sEngineName Engine for encryption. Values: Simple, Mcrypt + * @param string $sEngineName Engine for encryption. Values: Simple, Mcrypt, Sodium or OpenSSL + * @throws Exception This library is unkown */ function __construct($sEngineName = 'Mcrypt') { - if (($sEngineName == 'Mcrypt') && (!function_exists('mcrypt_module_open'))) - { - // Defaults to Simple encryption if the mcrypt module is not present - $sEngineName = 'Simple'; - } + switch($sEngineName){ + case 'Sodium': + if(!function_exists('sodium_crypto_secretbox_open')){ + $sEngineName = 'Simple'; + } + break; + case 'Mcrypt': + if(!function_exists('mcrypt_module_open')){ + if (function_exists('openssl_decrypt')) + { + $sEngineName = 'OpenSSLMcryptCompatibility'; + } + else + { + $sEngineName = 'Simple'; + } + } + break; + case 'OpenSSL': + if(!function_exists('openssl_decrypt')){ + $sEngineName = 'Simple'; + } + break; + case 'Simple': + break; + default: + throw new Exception(Dict::Format("Core:AttributeEncryptUnknownLibrary", $sEngineName)); + } + $sEngineName = 'SimpleCrypt' . $sEngineName . 'Engine'; $this->oEngine = new $sEngineName; } @@ -150,6 +194,7 @@ class SimpleCrypt */ interface CryptEngine { + public static function GetNewDefaultParams(); function Encrypt($key, $sString); function Decrypt($key, $encrypted_data); } @@ -161,7 +206,12 @@ interface CryptEngine */ class SimpleCryptSimpleEngine implements CryptEngine { - public function Encrypt($key, $sString) + public static function GetNewDefaultParams() + { + return array( 'lib' => 'Simple', 'key' => null); + } + + public function Encrypt($key, $sString) { $result = ''; for($i=1; $i<=strlen($sString); $i++) @@ -197,7 +247,13 @@ class SimpleCryptMcryptEngine implements CryptEngine { var $alg = MCRYPT_BLOWFISH; var $td = null; - + + public static function GetNewDefaultParams() + { + return array('lib' => 'Mcrypt', 'key' => null); + } + + public function __construct() { $this->td = mcrypt_module_open($this->alg,'','cbc',''); @@ -205,7 +261,7 @@ class SimpleCryptMcryptEngine implements CryptEngine public function Encrypt($key, $sString) { - $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($this->td), MCRYPT_RAND); // MCRYPT_RAND is the only choice on Windows prior to PHP 5.3 + $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($this->td), MCRYPT_RAND_URANDOM); // MCRYPT_RAND_URANDOM is now useable since itop requires php >= 5.6 mcrypt_generic_init($this->td, $key, $iv); if (empty($sString)) { @@ -223,7 +279,7 @@ class SimpleCryptMcryptEngine implements CryptEngine $r = mcrypt_generic_init($this->td, $key, $iv); if (($r < 0) || ($r === false)) { - $decrypted_data = '** decryption error **'; + $decrypted_data = Dict::S("Core:AttributeEncryptFailedToDecrypt"); } else { @@ -238,4 +294,121 @@ class SimpleCryptMcryptEngine implements CryptEngine mcrypt_module_close($this->td); } } -?> \ No newline at end of file +/** +* SodiumEngine requires Sodium extension +* Every encryption of the same string with the same key +* will return a different encrypted string. + * The key has to be SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long. + */ +class SimpleCryptSodiumEngine implements CryptEngine +{ + public static function GetNewDefaultParams() + { + return array('lib' => 'Sodium', 'key' => bin2hex(sodium_crypto_secretbox_keygen())); + } + + public function Encrypt($key, $sString) + { + $key = hex2bin($key); + $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); + $encrypted_string = sodium_crypto_secretbox($sString, $nonce, $key); + sodium_memzero($sString); + sodium_memzero($key); + return base64_encode($nonce.$encrypted_string); + } + + public function Decrypt($key, $encrypted_data) + { + $key = hex2bin($key); + $encrypted_data = base64_decode($encrypted_data); + $nonce = mb_substr($encrypted_data, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit'); + $encrypted_data = mb_substr($encrypted_data, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit'); + $plaintext = sodium_crypto_secretbox_open($encrypted_data, $nonce, $key); + if ($plaintext === false) + { + $plaintext = Dict::S("Core:AttributeEncryptFailedToDecrypt"); + } + sodium_memzero($encrypted_data); + sodium_memzero($key); + return $plaintext; + } + +} +class SimpleCryptOpenSSLEngine implements CryptEngine +{ + public static function GetNewDefaultParams() + { + return array('lib' => 'OpenSSL', 'key' => bin2hex(openssl_random_pseudo_bytes(32))); + } + + public function Encrypt($key, $sString) + { + $key = hex2bin($key); + $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length("AES-256-CBC")); + $encrypted_string = openssl_encrypt($sString, "AES-256-CBC", $key, 0 , $iv); + return $iv.$encrypted_string; + } + + public function Decrypt($key, $encrypted_data) + { + $key = hex2bin($key); + $iv = mb_substr($encrypted_data, 0, openssl_cipher_iv_length("AES-256-CBC"), '8bit'); + $encrypted_data = mb_substr($encrypted_data, openssl_cipher_iv_length("AES-256-CBC"), null, '8bit'); + $plaintext = openssl_decrypt($encrypted_data,"AES-256-CBC", $key, 0 , $iv); + if ($plaintext === false) + { + $plaintext = Dict::S("Core:AttributeEncryptFailedToDecrypt"); + } + return trim($plaintext); + } + +} + +class SimpleCryptOpenSSLMcryptCompatibilityEngine implements CryptEngine +{ + public static function GetNewDefaultParams() + { + return array('lib' => 'OpenSSLMcryptCompatibility', 'key' => null); + } + //fix for php < 7.1.8 (keys are Zero padded instead of cycle padded) + static private function MakeOpenSSLBlowfishKey($key) + { + if("$key" === '') + { + return $key; + } + $len = (16+2)*4; + while(strlen($key) < $len) + { + $key .= $key; + } + $key = substr($key, 0, $len); + return $key; + } + public function Encrypt($key, $sString) + { + $key = SimpleCryptOpenSSLMcryptCompatibilityEngine::MakeOpenSSLBlowfishKey($key); + $blockSize = 8; + $len = strlen($sString); + $paddingLen = intval (($len + $blockSize -1) / $blockSize) * $blockSize - $len; + $padding = str_repeat("\0", $paddingLen); + $sData = $sString . $padding; + $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length("BF-CBC")); + $encrypted_string = openssl_encrypt($sData, "BF-CBC", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); + return $iv.$encrypted_string; + } + + public function Decrypt($key, $encrypted_data) + { + $key = SimpleCryptOpenSSLMcryptCompatibilityEngine::MakeOpenSSLBlowfishKey($key); + $iv = mb_substr($encrypted_data, 0, openssl_cipher_iv_length("BF-CBC"), '8bit'); + $encrypted_data = mb_substr($encrypted_data, openssl_cipher_iv_length("BF-CBC"), null, '8bit'); + $plaintext = openssl_decrypt($encrypted_data,"BF-CBC", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); + if ($plaintext === false) + { + $plaintext = Dict::S("Core:AttributeEncryptFailedToDecrypt"); + } + return trim($plaintext); + } + +} diff --git a/dictionaries/cs.dictionary.itop.core.php b/dictionaries/cs.dictionary.itop.core.php index b238f2bca..c812dda78 100755 --- a/dictionaries/cs.dictionary.itop.core.php +++ b/dictionaries/cs.dictionary.itop.core.php @@ -86,6 +86,8 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array( 'Core:AttributeEncryptedString' => 'Šifrovaný řetězec', 'Core:AttributeEncryptedString+' => 'Řetězec šifrovaný lokálním klíčem', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Text', 'Core:AttributeText+' => 'Víceřádkový řetězec znaků', diff --git a/dictionaries/da.dictionary.itop.core.php b/dictionaries/da.dictionary.itop.core.php index 0aee2a8b3..67e12add5 100644 --- a/dictionaries/da.dictionary.itop.core.php +++ b/dictionaries/da.dictionary.itop.core.php @@ -1428,6 +1428,8 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array( 'Core:AttributePassword+' => '', 'Core:AttributeEncryptedString' => 'Krypteret streng', 'Core:AttributeEncryptedString+' => '', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Tekst', 'Core:AttributeText+' => '', 'Core:AttributeHTML' => 'HTML', diff --git a/dictionaries/de.dictionary.itop.core.php b/dictionaries/de.dictionary.itop.core.php index 60368e64d..6cb5ddf64 100644 --- a/dictionaries/de.dictionary.itop.core.php +++ b/dictionaries/de.dictionary.itop.core.php @@ -354,6 +354,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', array( 'Core:AttributePassword+' => 'Passwort eines externen Geräts', 'Core:AttributeEncryptedString' => 'verschlüsselter String', 'Core:AttributeEncryptedString+' => 'mit einem lokalen Schüssel verschlüsselter String', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Text', 'Core:AttributeText+' => 'Mehrzeiliger String', 'Core:AttributeHTML' => 'HTML', diff --git a/dictionaries/en.dictionary.itop.core.php b/dictionaries/en.dictionary.itop.core.php index 90580134d..714f6faaa 100644 --- a/dictionaries/en.dictionary.itop.core.php +++ b/dictionaries/en.dictionary.itop.core.php @@ -84,6 +84,8 @@ Dict::Add('EN US', 'English', 'English', array( 'Core:AttributeEncryptedString' => 'Encrypted string', 'Core:AttributeEncryptedString+' => 'String encrypted with a local key', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **', 'Core:AttributeText' => 'Text', 'Core:AttributeText+' => 'Multiline character string', diff --git a/dictionaries/es_cr.dictionary.itop.core.php b/dictionaries/es_cr.dictionary.itop.core.php index 0ea8ad53b..97b10a05e 100644 --- a/dictionaries/es_cr.dictionary.itop.core.php +++ b/dictionaries/es_cr.dictionary.itop.core.php @@ -84,7 +84,9 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array( 'Core:AttributeEncryptedString' => 'Cadena encriptada', 'Core:AttributeEncryptedString+' => 'Cadena encriptada con llave local', - + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', + 'Core:AttributeText' => 'Texto', 'Core:AttributeText+' => 'Cadena de Múltiples Líneas de Caracteres', diff --git a/dictionaries/fr.dictionary.itop.core.php b/dictionaries/fr.dictionary.itop.core.php index f98cd1dee..b15a47e6e 100644 --- a/dictionaries/fr.dictionary.itop.core.php +++ b/dictionaries/fr.dictionary.itop.core.php @@ -127,6 +127,8 @@ Dict::Add('FR FR', 'French', 'Français', array( 'Class:CMDBChangeOpSetAttributeOneWayPassword/Attribute:prev_pwd+' => '', 'Class:CMDBChangeOpSetAttributeEncrypted' => 'Champ chiffré', 'Class:CMDBChangeOpSetAttributeEncrypted+' => '', + 'Core:AttributeEncryptUnknownLibrary' => 'La bibliothèque de chiffrement specifée (%1$s) est inconnue', + 'Core:AttributeEncryptFailedToDecrypt' => '** erreur de déchiffrage **', 'Class:CMDBChangeOpSetAttributeEncrypted/Attribute:prevstring' => 'Ancienne valeur', 'Class:CMDBChangeOpSetAttributeEncrypted/Attribute:prevstring+' => '', 'Class:CMDBChangeOpSetAttributeText' => 'Modification de texte', diff --git a/dictionaries/hu.dictionary.itop.core.php b/dictionaries/hu.dictionary.itop.core.php index c485e73a9..6293b643c 100755 --- a/dictionaries/hu.dictionary.itop.core.php +++ b/dictionaries/hu.dictionary.itop.core.php @@ -337,6 +337,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array( 'Core:AttributePassword+' => '', 'Core:AttributeEncryptedString' => 'Encrypted string', 'Core:AttributeEncryptedString+' => '', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Text', 'Core:AttributeText+' => '', 'Core:AttributeHTML' => 'HTML', diff --git a/dictionaries/it.dictionary.itop.core.php b/dictionaries/it.dictionary.itop.core.php index 808d17ba4..f0d02cf80 100644 --- a/dictionaries/it.dictionary.itop.core.php +++ b/dictionaries/it.dictionary.itop.core.php @@ -78,6 +78,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array( 'Core:AttributeEncryptedString' => 'Stringa criptata', 'Core:AttributeEncryptedString+' => 'Stringa cripta con una chiave locale', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Testo', 'Core:AttributeText+' => 'Stringa di caratteri multilinea', diff --git a/dictionaries/ja.dictionary.itop.core.php b/dictionaries/ja.dictionary.itop.core.php index 0f4b0f1a4..0678bf3ee 100644 --- a/dictionaries/ja.dictionary.itop.core.php +++ b/dictionaries/ja.dictionary.itop.core.php @@ -356,6 +356,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', array( 'Core:AttributePassword+' => '外部デバイス用パスワード', 'Core:AttributeEncryptedString' => '暗号化文字列', 'Core:AttributeEncryptedString+' => 'ローカルキーで暗号化された文字列', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'テキスト', 'Core:AttributeText+' => '複数行文字列', 'Core:AttributeHTML' => 'HTML', diff --git a/dictionaries/nl.dictionary.itop.core.php b/dictionaries/nl.dictionary.itop.core.php index d4f76712e..aa9a876cf 100644 --- a/dictionaries/nl.dictionary.itop.core.php +++ b/dictionaries/nl.dictionary.itop.core.php @@ -89,6 +89,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array( 'Core:AttributeEncryptedString' => 'Gecodeerde string', 'Core:AttributeEncryptedString+' => 'String gecodeerd met een locale key', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Text', 'Core:AttributeText+' => 'Multiline character string', diff --git a/dictionaries/pt_br.dictionary.itop.core.php b/dictionaries/pt_br.dictionary.itop.core.php index 1475e55e7..1e6e3fd6f 100644 --- a/dictionaries/pt_br.dictionary.itop.core.php +++ b/dictionaries/pt_br.dictionary.itop.core.php @@ -84,6 +84,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( 'Core:AttributeEncryptedString' => 'String encriptada', 'Core:AttributeEncryptedString+' => 'String encriptada com uma chave local', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Texto', 'Core:AttributeText+' => 'Cadeia de caracteres Multi-linha', diff --git a/dictionaries/ru.dictionary.itop.core.php b/dictionaries/ru.dictionary.itop.core.php index 768d9b134..9ca3f9b27 100644 --- a/dictionaries/ru.dictionary.itop.core.php +++ b/dictionaries/ru.dictionary.itop.core.php @@ -70,6 +70,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', array( 'Core:AttributeEncryptedString' => 'Шифр.значение', 'Core:AttributeEncryptedString+' => 'String encrypted with a local key', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Текст~~', 'Core:AttributeText+' => 'Multiline character string', diff --git a/dictionaries/tr.dictionary.itop.core.php b/dictionaries/tr.dictionary.itop.core.php index 2a6912e46..6ca57a55f 100644 --- a/dictionaries/tr.dictionary.itop.core.php +++ b/dictionaries/tr.dictionary.itop.core.php @@ -444,6 +444,8 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array( 'Core:AttributePassword+' => 'Password of an external device~~', 'Core:AttributeEncryptedString' => 'Encrypted string~~', 'Core:AttributeEncryptedString+' => 'String encrypted with a local key~~', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Text~~', 'Core:AttributeText+' => 'Multiline character string~~', 'Core:AttributeHTML' => 'HTML~~', diff --git a/dictionaries/zh.dictionary.itop.core.php b/dictionaries/zh.dictionary.itop.core.php index 3ccff12d7..c5acc2a38 100644 --- a/dictionaries/zh.dictionary.itop.core.php +++ b/dictionaries/zh.dictionary.itop.core.php @@ -443,6 +443,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array( 'Core:AttributePassword+' => 'Password of an external device~~', 'Core:AttributeEncryptedString' => 'Encrypted string~~', 'Core:AttributeEncryptedString+' => 'String encrypted with a local key~~', + 'Core:AttributeEncryptUnknownLibrary' => 'Encryption library specified (%1$s) unknown~~', + 'Core:AttributeEncryptFailedToDecrypt' => '** decryption error **~~', 'Core:AttributeText' => 'Text~~', 'Core:AttributeText+' => 'Multiline character string~~', 'Core:AttributeHTML' => 'HTML~~', diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index 469d6a0b6..e9c041bdc 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -91,7 +91,9 @@ class SetupUtils $aResult = array_merge($aResult, $aWritableDirsErrors); $aMandatoryExtensions = array('mysqli', 'iconv', 'simplexml', 'soap', 'hash', 'json', 'session', 'pcre', 'dom', 'zlib', 'zip'); - $aOptionalExtensions = array('mcrypt' => 'Strong encryption will not be used.', + $aOptionalExtensions = array( 'mcrypt, sodium or openssl' => array( 'mcrypt' => 'Strong encryption will not be used.', + 'sodium' => 'Strong encryption will not be used.', + 'openssl' => 'Strong encryption will not be used.',), 'ldap' => 'LDAP authentication will be disabled.', 'gd' => 'PDF export will be disabled. Also, image resizing will be disabled on profile pictures (May increase database size).'); asort($aMandatoryExtensions); // Sort the list to look clean ! @@ -125,13 +127,38 @@ class SetupUtils $aMissingExtensions = array(); foreach($aOptionalExtensions as $sExtension => $sMessage) { - if (extension_loaded($sExtension)) + //if sMessage is an array, extensions in it are conditional between them + if (is_array($sMessage)) { - $aExtensionsOk[] = $sExtension; + $bIsAtLeastOneLoaded = false; + $sConditionalMissingMessage = ''; + foreach($sMessage as $sConditionalExtension => $sConditionalMessage) + { + if (extension_loaded($sConditionalExtension)) + { + $bIsAtLeastOneLoaded = true; + $aExtensionsOk[] = $sConditionalExtension; + } + else + { + $sConditionalMissingMessage = $sConditionalMessage; + } + } + if(!$bIsAtLeastOneLoaded) + { + $aMissingExtensions[$sExtension] = $sConditionalMissingMessage; + } } else { - $aMissingExtensions[$sExtension] = $sMessage; + if (extension_loaded($sExtension)) + { + $aExtensionsOk[] = $sExtension; + } + else + { + $aMissingExtensions[$sExtension] = $sMessage; + } } } if (count($aExtensionsOk) > 0)