diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f1e7f2..c7fd613 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ --- develop --- +* issue#257: Remove /bin/sh fallback execution path for alert commands * issue: Making changes to support Cacti 1.3 * issue: Don't use MyISAM for non-analytical tables * issue: The install advisor for Syslog was broken in current Cacti releases diff --git a/functions.php b/functions.php index 9bd3223..214b52e 100644 --- a/functions.php +++ b/functions.php @@ -1521,23 +1521,23 @@ function syslog_process_alert($alert, $sql, $params, $count, $hostname = '') { } if (trim($alert['command']) != '' && !$found) { - $command = alert_replace_variables($alert, $results, $hostname); - - $logMessage = "SYSLOG NOTICE: Executing '$command'"; - - $cparts = explode(' ', $command); - - if (is_executable($cparts[0])) { + $command = alert_replace_variables($alert, $results, $hostname); + $cparts = preg_split('/\s+/', trim($command)); + /* trim surrounding quotes so paths like "/usr/bin/cmd" resolve correctly */ + $executable = trim($cparts[0], '"\''); + $output = array(); + $returnCode = 0; + + if (cacti_sizeof($cparts) && is_executable($executable)) { exec($command, $output, $returnCode); + cacti_log("SYSLOG NOTICE: Executing '$command' Command return code: $returnCode", true, 'SYSTEM'); } else { - exec('/bin/sh ' . $command, $output, $returnCode); + $returnCode = 126; + $reason = (strpos($executable, DIRECTORY_SEPARATOR) === false) + ? 'PATH-based lookups are not supported; use an absolute path' + : 'file not found or not marked executable'; + cacti_log("SYSLOG ERROR: Alert command is not executable: '$command' -- $reason", false, 'SYSTEM'); } - - // Append the return code to the log message without the dot - $logMessage .= " Command return code: $returnCode"; - - // Log the combined message - cacti_log($logMessage, true, 'SYSTEM'); } } @@ -1581,23 +1581,23 @@ function syslog_process_alert($alert, $sql, $params, $count, $hostname = '') { } if (trim($alert['command']) != '' && !$found) { - $command = alert_replace_variables($alert, $results, $hostname); - - $logMessage = "SYSLOG NOTICE: Executing '$command'"; - - $cparts = explode(' ', $command); - - if (is_executable($cparts[0])) { + $command = alert_replace_variables($alert, $results, $hostname); + $cparts = preg_split('/\s+/', trim($command)); + /* trim surrounding quotes so paths like "/usr/bin/cmd" resolve correctly */ + $executable = trim($cparts[0], '"\''); + $output = array(); + $returnCode = 0; + + if (cacti_sizeof($cparts) && is_executable($executable)) { exec($command, $output, $returnCode); + cacti_log("SYSLOG NOTICE: Executing '$command' Command return code: $returnCode", true, 'SYSTEM'); } else { - exec('/bin/sh ' . $command, $output, $returnCode); + $returnCode = 126; + $reason = (strpos($executable, DIRECTORY_SEPARATOR) === false) + ? 'PATH-based lookups are not supported; use an absolute path' + : 'file not found or not marked executable'; + cacti_log("SYSLOG ERROR: Alert command is not executable: '$command' -- $reason", false, 'SYSTEM'); } - - // Append the return code to the log message without the dot - $logMessage .= " Command return code: $returnCode"; - - // Log the combined message - cacti_log($logMessage, true, 'SYSTEM'); } } } @@ -2421,4 +2421,3 @@ function alert_replace_variables($alert, $results, $hostname = '') { return $command; } - diff --git a/tests/regression/issue257_remove_shell_fallback_test.php b/tests/regression/issue257_remove_shell_fallback_test.php new file mode 100644 index 0000000..3cb5a84 --- /dev/null +++ b/tests/regression/issue257_remove_shell_fallback_test.php @@ -0,0 +1,30 @@ +