mirror of
https://github.com/serghey-rodin/vesta.git
synced 2025-08-14 10:37:39 -07:00
🔒 ♻️ Implement secure exec
wrapper functions.
This commit is contained in:
parent
6e13036780
commit
8e951ac72e
115 changed files with 1345 additions and 1986 deletions
85
web/inc/exec.php
Normal file
85
web/inc/exec.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
// Secure `exec` wrapper functions
|
||||
|
||||
define('SUDO_CMD', '/usr/bin/sudo');
|
||||
define('VESTA_BIN_DIR', '/usr/local/vesta/bin/');
|
||||
|
||||
define('VESTA_CMD', SUDO_CMD.' '.VESTA_BIN_DIR);
|
||||
|
||||
|
||||
function check_error($return_var) {
|
||||
if ($return_var > 0) {
|
||||
header('Location: /error/');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function check_return_code($return_var, $output) {
|
||||
if ($return_var != 0) {
|
||||
$error = implode('<br>', $output);
|
||||
if (empty($error)) $error = __('Error code:', $return_var);
|
||||
$_SESSION['error_msg'] = $error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build shell command arguments from a string array.
|
||||
* @param string[] $arguments Unescaped command line arguments. (eg. ['-a', "b'c"], default: [])
|
||||
* @return string Escaped arguments.
|
||||
*/
|
||||
function build_shell_args($arguments=[]) {
|
||||
$ret = [];
|
||||
// Convert $arguments to an array
|
||||
if (!is_array($arguments)) $arguments = !is_null($arguments) ? [$arguments] : [];
|
||||
foreach ($arguments as $arg) {
|
||||
// Convert $arg to a string if $arg is an array (for an argument like this: ?abc[def]=ghi)
|
||||
if (is_array($arg)) $arg = implode('', $arg);
|
||||
// Convert $arg to a string (just in case)
|
||||
if (!is_string($arg)) $arg = (string)$arg;
|
||||
// Append the argument
|
||||
$ret[] = escapeshellarg($arg);
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command.
|
||||
* @param string $command Command to execute. (eg. ls)
|
||||
* @param string[] $arguments (optional) Unescaped command line arguments. (eg. ['-a', '/'], default: [])
|
||||
* @param string &$output (optional) Variable to contain output from the command.
|
||||
* @return int Exit code (return status) of the executed command.
|
||||
*/
|
||||
function safe_exec($command, $arguments=[], &$output=null) {
|
||||
$cmd = build_shell_args($command);
|
||||
$arg = build_shell_args($arguments);
|
||||
if (!empty($arg)) {
|
||||
$cmd .= ' ' . $arg;
|
||||
}
|
||||
// Execute
|
||||
exec($cmd, $rawOutput, $status);
|
||||
$output = implode("\n", $rawOutput);
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a vesta command line APIs (VESTA_CMD/v-*).
|
||||
* (Wrapper function of `safe_exec`.)
|
||||
* @see safe_exec
|
||||
* @param string $command Command to execute. (eg. v-search-object)
|
||||
* @param string[] $arguments (optional) Unescaped command line arguments. (eg. ["We've", 'json'], default: [])
|
||||
* @param bool $checkReturn (optional) If this set to true, check_return_code will be called after the command executes. (default: true)
|
||||
* @param string &$output (optional) Variable to contain output from the command.
|
||||
* @return int Exit code (return status) of the executed command.
|
||||
*/
|
||||
function v_exec($command, $arguments=[], $checkReturn=true, &$output=null) {
|
||||
// Check command
|
||||
if (preg_match('#^\.*$|/#', $command)) return -1;
|
||||
// Convert $arguments to an array
|
||||
if (!is_array($arguments)) $arguments = !is_null($arguments) ? [$arguments] : [];
|
||||
// Execute
|
||||
$status = safe_exec([SUDO_CMD, VESTA_BIN_DIR.$command], $arguments, $output);
|
||||
if ($checkReturn) {
|
||||
check_return_code($status, explode("\n", $output));
|
||||
}
|
||||
return $status;
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
// Functions for internationalization
|
||||
|
||||
require_once(__DIR__.'/exec.php');
|
||||
|
||||
/**
|
||||
* Translates string to given language in first parameter, key given in second parameter (dynamically loads required language). Works like spritf from second parameter
|
||||
* @global array $LANG Associative array of language pharses
|
||||
|
@ -16,19 +18,19 @@ function _translate() {
|
|||
$key = $args[1];
|
||||
|
||||
if (!isset($LANG[$l])) {
|
||||
require_once($_SERVER['DOCUMENT_ROOT'].'/inc/i18n/'.$l.'.php');
|
||||
require_once(__DIR__."/i18n/$l.php");
|
||||
}
|
||||
|
||||
if (!isset($LANG[$l][$key])) {
|
||||
$text=$key;
|
||||
$text = $key;
|
||||
} else {
|
||||
$text=$LANG[$l][$key];
|
||||
$text = $LANG[$l][$key];
|
||||
}
|
||||
|
||||
array_shift($args);
|
||||
if (count($args)>1) {
|
||||
if (count($args) > 1) {
|
||||
$args[0] = $text;
|
||||
return call_user_func_array("sprintf",$args);
|
||||
return call_user_func_array('sprintf', $args);
|
||||
} else {
|
||||
return $text;
|
||||
}
|
||||
|
@ -42,8 +44,8 @@ function _translate() {
|
|||
*/
|
||||
function __() {
|
||||
$args = func_get_args();
|
||||
array_unshift($args,$_SESSION['language']);
|
||||
return call_user_func_array("_translate",$args);
|
||||
array_unshift($args, $_SESSION['language']);
|
||||
return call_user_func_array('_translate', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,16 +88,15 @@ function detect_user_language($fallback='en') {
|
|||
arsort($accept_langs_sorted);
|
||||
|
||||
// List languages
|
||||
exec (VESTA_CMD."v-list-sys-languages json", $output, $return_var);
|
||||
$languages = json_decode(implode('', $output), true);
|
||||
unset($output);
|
||||
v_exec('v-list-sys-languages', ['json'], false, $output);
|
||||
$languages = json_decode($output, true);
|
||||
|
||||
// Find best matching language
|
||||
foreach ($accept_langs_sorted as $user_lang => $dummy) {
|
||||
foreach ($accept_langs_sorted as $req_lang => $dummy) {
|
||||
$decision = '';
|
||||
foreach ($languages as $prov_lang) {
|
||||
if (strlen($decision) > strlen($prov_lang)) continue;
|
||||
if (strpos($user_lang, $prov_lang) !== false) {
|
||||
if (stripos($req_lang, $prov_lang) !== false) {
|
||||
$decision = $prov_lang;
|
||||
}
|
||||
}
|
||||
|
@ -109,4 +110,4 @@ function detect_user_language($fallback='en') {
|
|||
// Store result for reusing
|
||||
$user_lang = $fallback;
|
||||
return $user_lang;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,14 +8,15 @@ if (empty($argv[1])) {
|
|||
|
||||
$options = getopt("s:f:");
|
||||
|
||||
require_once(__DIR__.'/exec.php');
|
||||
|
||||
define('NO_AUTH_REQUIRED',true);
|
||||
define('NO_AUTH_REQUIRED', true);
|
||||
include("/usr/local/vesta/web/inc/main.php");
|
||||
|
||||
// Set system language
|
||||
exec (VESTA_CMD . "v-list-sys-config json", $output, $return_var);
|
||||
$data = json_decode(implode('', $output), true);
|
||||
if (!empty( $data['config']['LANGUAGE'])) {
|
||||
v_exec('v-list-sys-config', ['json'], false, $output);
|
||||
$data = json_decode($output, true);
|
||||
if (!empty($data['config']['LANGUAGE'])) {
|
||||
$_SESSION['language'] = $data['config']['LANGUAGE'];
|
||||
} else {
|
||||
$_SESSION['language'] = 'en';
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?php
|
||||
session_start();
|
||||
|
||||
require_once($_SERVER['DOCUMENT_ROOT'].'/inc/i18n.php');
|
||||
require_once(__DIR__ . '/exec.php');
|
||||
require_once(__DIR__ . '/i18n.php');
|
||||
|
||||
// Check system settings
|
||||
if ((!isset($_SESSION['VERSION'])) && (!defined('NO_AUTH_REQUIRED'))) {
|
||||
|
@ -25,8 +26,6 @@ if (isset($_SESSION['user'])) {
|
|||
}
|
||||
}
|
||||
|
||||
define('VESTA_CMD', '/usr/bin/sudo /usr/local/vesta/bin/');
|
||||
|
||||
$i = 0;
|
||||
|
||||
if (isset($_SESSION['language'])) {
|
||||
|
@ -60,10 +59,10 @@ if (isset($_SESSION['look']) && ( $_SESSION['look'] != 'admin' )) {
|
|||
}
|
||||
|
||||
function get_favourites(){
|
||||
exec (VESTA_CMD."v-list-user-favourites ".$_SESSION['user']." json", $output, $return_var);
|
||||
// $data = json_decode(implode('', $output).'}', true);
|
||||
$data = json_decode(implode('', $output), true);
|
||||
$data = array_reverse($data,true);
|
||||
v_exec('v-list-user-favourites', [$_SESSION['user'], 'json'], false, $output);
|
||||
// $data = json_decode($output.'}', true);
|
||||
$data = json_decode($output, true);
|
||||
$data = array_reverse($data, true);
|
||||
$favourites = array();
|
||||
|
||||
foreach($data['Favourites'] as $key => $favourite){
|
||||
|
@ -71,7 +70,7 @@ function get_favourites(){
|
|||
|
||||
$items = explode(',', $favourite);
|
||||
foreach($items as $item){
|
||||
if($item)
|
||||
if ($item)
|
||||
$favourites[$key][trim($item)] = 1;
|
||||
}
|
||||
}
|
||||
|
@ -79,34 +78,15 @@ function get_favourites(){
|
|||
$_SESSION['favourites'] = $favourites;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function check_error($return_var) {
|
||||
if ( $return_var > 0 ) {
|
||||
header("Location: /error/");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function check_return_code($return_var,$output) {
|
||||
if ($return_var != 0) {
|
||||
$error = implode('<br>', $output);
|
||||
if (empty($error)) $error = __('Error code:',$return_var);
|
||||
$_SESSION['error_msg'] = $error;
|
||||
}
|
||||
}
|
||||
|
||||
function top_panel($user, $TAB) {
|
||||
global $panel;
|
||||
$command = VESTA_CMD."v-list-user '".$user."' 'json'";
|
||||
exec ($command, $output, $return_var);
|
||||
if ( $return_var > 0 ) {
|
||||
header("Location: /error/");
|
||||
$return_var = v_exec('v-list-user', [$user, 'json'], false, $output);
|
||||
if ($return_var > 0) {
|
||||
header('Location: /error/');
|
||||
exit;
|
||||
}
|
||||
$panel = json_decode(implode('', $output), true);
|
||||
unset($output);
|
||||
if ( $user == 'admin' ) {
|
||||
$panel = json_decode($output, true);
|
||||
if ($user == 'admin') {
|
||||
include($_SERVER['DOCUMENT_ROOT'].'/templates/admin/panel.html');
|
||||
} else {
|
||||
include($_SERVER['DOCUMENT_ROOT'].'/templates/user/panel.html');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue