diff --git a/core/config.class.inc.php b/core/config.class.inc.php index 5a4fd3c11..073374498 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -1819,26 +1819,6 @@ class Config return (array_key_exists($sPropCode, $this->m_aSettings)); } - public static function Validate(string $sContents) - { - $oiTopConfigValidator = new iTopConfigAstValidator(); - $oiTopConfigValidator->Validate($sContents); - - /// 2 - only after we are sure that there is no malicious code, we can perform a syntax check! - $oiTopConfigValidator = new iTopConfigSyntaxValidator(); - $oiTopConfigValidator->Validate($sContents); - } - - function DBPasswordInNewConfigIsOk() - { - $bIsWindows = (array_key_exists('WINDIR', $_SERVER) || array_key_exists('windir', $_SERVER)); - - if ($bIsWindows && (preg_match("/[%!\"]/U", $this->Get('db_pwd')) !== 0)) { - return false; - } - - return true; - } /** * @return string identifier that can be used for example to name WebStorage/SessionStorage keys (they diff --git a/datamodels/2.x/itop-config/config.php b/datamodels/2.x/itop-config/config.php index a211f37c2..69ca685cc 100644 --- a/datamodels/2.x/itop-config/config.php +++ b/datamodels/2.x/itop-config/config.php @@ -6,6 +6,7 @@ use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory; use Combodo\iTop\Application\WebPage\iTopConfigEditorPage; +use Combodo\iTop\Config\Validator\iTopConfigValidator; require_once(APPROOT.'application/startup.inc.php'); @@ -24,11 +25,11 @@ try { if (MetaModel::GetConfig()->Get('demo_mode')) { - throw new Exception(Dict::S('config-not-allowed-in-demo'), iTopConfigEditorPage::CONFIG_INFO); + throw new Exception(Dict::S('config-not-allowed-in-demo'), iTopConfigValidator::CONFIG_INFO); } if (MetaModel::GetModuleSetting('itop-config', 'config_editor', '') == 'disabled') { - throw new Exception(Dict::S('config-interactive-not-allowed'), iTopConfigEditorPage::CONFIG_WARNING); + throw new Exception(Dict::S('config-interactive-not-allowed'), iTopConfigValidator::CONFIG_WARNING); } $sConfigFile = APPROOT.'conf/'.utils::GetCurrentEnvironment().'/config-itop.php'; @@ -44,24 +45,25 @@ try { try { if ($sOperation == 'revert') { - throw new Exception(Dict::S('config-reverted'), iTopConfigEditorPage::CONFIG_WARNING); + throw new Exception(Dict::S('config-reverted'), iTopConfigValidator::CONFIG_WARNING); } if ($sOperation == 'save') { $sTransactionId = utils::ReadParam('transaction_id', '', false, 'transaction_id'); if (!utils::IsTransactionValid($sTransactionId, true)) { - throw new Exception(Dict::S('config-error-transaction'), iTopConfigEditorPage::CONFIG_ERROR); + throw new Exception(Dict::S('config-error-transaction'), iTopConfigValidator::CONFIG_ERROR); } $sChecksum = utils::ReadParam('checksum'); if ($sChecksum !== $sConfigChecksum) { - throw new Exception(Dict::S('config-error-file-changed'), iTopConfigEditorPage::CONFIG_ERROR); + throw new Exception(Dict::S('config-error-file-changed'), iTopConfigValidator::CONFIG_ERROR); } if ($sConfig === $sOriginalConfig) { - throw new Exception(Dict::S('config-no-change'), iTopConfigEditorPage::CONFIG_INFO); + throw new Exception(Dict::S('config-no-change'), iTopConfigValidator::CONFIG_INFO); } - Config::Validate($sConfig); // throws exceptions + $oValidator = new iTopConfigValidator(); + $oValidator->Validate($sConfig);// throws exceptions @chmod($sConfigFile, 0770); // Allow overwriting the file $sTmpFile = tempnam(SetupUtils::GetTmpDir(), 'itop-cfg-'); @@ -82,7 +84,7 @@ try { @unlink($sTmpFile); @chmod($sConfigFile, 0440); // Read-only - if ($oTempConfig->DBPasswordInNewConfigIsOk()) { + if ($oValidator->DBPasswordIsOk($oTempConfig->Get('db_pwd'))) { $oAlert = AlertUIBlockFactory::MakeForSuccess('', Dict::S('config-saved')); } else { $oAlert = AlertUIBlockFactory::MakeForInformation('', Dict::S('config-saved-warning-db-password')); diff --git a/datamodels/2.x/itop-config/module.itop-config.php b/datamodels/2.x/itop-config/module.itop-config.php index 2c8f2d2a1..a57c4f0af 100644 --- a/datamodels/2.x/itop-config/module.itop-config.php +++ b/datamodels/2.x/itop-config/module.itop-config.php @@ -22,6 +22,7 @@ SetupWebPage::AddModule( 'src/Validator/ConfigNodesVisitor.php', 'src/Validator/iTopConfigAstValidator.php', 'src/Validator/iTopConfigSyntaxValidator.php', + 'src/Validator/iTopConfigValidator.php', ), 'webservice' => array(), 'dictionary' => array( diff --git a/datamodels/2.x/itop-config/src/Validator/iTopConfigAstValidator.php b/datamodels/2.x/itop-config/src/Validator/iTopConfigAstValidator.php index 0d8cbfba9..6d0fcf2fb 100644 --- a/datamodels/2.x/itop-config/src/Validator/iTopConfigAstValidator.php +++ b/datamodels/2.x/itop-config/src/Validator/iTopConfigAstValidator.php @@ -31,10 +31,10 @@ class iTopConfigAstValidator $aInitialNodes = $oParser->parse($sConfig); } catch (\Error $e) { $sMessage = 'Invalid configuration: '. \Dict::Format('config-parse-error', $e->getMessage(), $e->getLine()); - throw new \Exception($sMessage, 0, $e); + throw new \Exception($sMessage, iTopConfigValidator::CONFIG_ERROR, $e); }catch (\Exception $e) { $sMessage = 'Invalid configuration: '. \Dict::Format('config-parse-error', $e->getMessage(), $e->getLine()); - throw new \Exception($sMessage, 0, $e); + throw new \Exception($sMessage, iTopConfigValidator::CONFIG_ERROR, $e); } $oTraverser = new NodeTraverser(); diff --git a/datamodels/2.x/itop-config/src/Validator/iTopConfigSyntaxValidator.php b/datamodels/2.x/itop-config/src/Validator/iTopConfigSyntaxValidator.php index 7c5c6a168..4ecbed82e 100644 --- a/datamodels/2.x/itop-config/src/Validator/iTopConfigSyntaxValidator.php +++ b/datamodels/2.x/itop-config/src/Validator/iTopConfigSyntaxValidator.php @@ -17,8 +17,7 @@ class iTopConfigSyntaxValidator */ public function Validate($sRawConfig) { - try - { + try { ini_set('display_errors', 1); ob_start(); // in PHP < 7.0.0 syntax errors are in output @@ -27,29 +26,24 @@ class iTopConfigSyntaxValidator eval('if(0){'.trim($sConfig).'}'); $sNoise = trim(ob_get_contents()); } - catch (\Error $e) - { + catch (\Error $e) { // ParseError only thrown in PHP7 - throw new \Exception('Error in configuration: '.$e->getMessage().' at line '.$e->getLine()); + throw new \Exception('Error in configuration: '.$e->getMessage().' at line '.$e->getLine(), iTopConfigValidator::CONFIG_ERROR); } - finally - { + finally { ob_end_clean(); } - if (strlen($sNoise) > 0) - { - if (preg_match("/(Error|Parse error|Notice|Warning): (.+) in \S+ : eval\(\)'d code on line (\d+)/i", strip_tags($sNoise), $aMatches)) - { + if (strlen($sNoise) > 0) { + if (preg_match("/(Error|Parse error|Notice|Warning): (.+) in \S+ : eval\(\)'d code on line (\d+)/i", strip_tags($sNoise), $aMatches)) { $sMessage = $aMatches[2]; $sLine = $aMatches[3]; $sMessage = \Dict::Format('config-parse-error', $sMessage, $sLine); - throw new \Exception($sMessage); + throw new \Exception($sMessage, iTopConfigValidator::CONFIG_ERROR); } - else - { + else { // Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack) - throw new \Exception('Syntax error in configuration file: '.$sNoise.''); + throw new \Exception('Syntax error in configuration file: '.$sNoise.'', iTopConfigValidator::CONFIG_ERROR); } } } diff --git a/datamodels/2.x/itop-config/src/Validator/iTopConfigValidator.php b/datamodels/2.x/itop-config/src/Validator/iTopConfigValidator.php new file mode 100644 index 000000000..f0c42fd07 --- /dev/null +++ b/datamodels/2.x/itop-config/src/Validator/iTopConfigValidator.php @@ -0,0 +1,35 @@ +Validate($sRawConfig); + + /// 2 - only after we are sure that there is no malicious code, we can perform a syntax check! + $oiTopConfigValidator = new iTopConfigSyntaxValidator(); + $oiTopConfigValidator->Validate($sRawConfig); + } + + function DBPasswordIsOk($sPassword) + { + $bIsWindows = (array_key_exists('WINDIR', $_SERVER) || array_key_exists('windir', $_SERVER)); + + if ($bIsWindows && (preg_match("/[%!\"]/U", $sPassword) !== 0)) { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/sources/Application/WebPage/iTopConfigEditorPage.php b/sources/Application/WebPage/iTopConfigEditorPage.php index b2567723f..73d74fd19 100644 --- a/sources/Application/WebPage/iTopConfigEditorPage.php +++ b/sources/Application/WebPage/iTopConfigEditorPage.php @@ -2,6 +2,7 @@ namespace Combodo\iTop\Application\WebPage; use AsyncTask; +use Combodo\iTop\Config\Validator\iTopConfigValidator; use Dict; use ReflectionClass; use utils; @@ -15,9 +16,6 @@ use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory; class iTopConfigEditorPage extends iTopWebPage { - const CONFIG_ERROR = 0; - const CONFIG_WARNING = 1; - const CONFIG_INFO = 2; public function __construct() { @@ -35,8 +33,8 @@ class iTopConfigEditorPage extends iTopWebPage public function AddAlertFromException(\Exception $e) { $oAlert = match ($e->getCode()) { - self::CONFIG_WARNING => AlertUIBlockFactory::MakeForWarning('', $e->getMessage()), - self::CONFIG_INFO => AlertUIBlockFactory::MakeForInformation('', $e->getMessage()), + iTopConfigValidator::CONFIG_WARNING => AlertUIBlockFactory::MakeForWarning('', $e->getMessage()), + iTopConfigValidator::CONFIG_INFO => AlertUIBlockFactory::MakeForInformation('', $e->getMessage()), default => AlertUIBlockFactory::MakeForDanger('', $e->getMessage()), }; $this->AddUiBlock($oAlert);