Просмотр исходного кода

WIP: Hardening of installer security and improving usability (#4690)

* Disallow usage of running command without user in installers

* Fix format

---------

Co-authored-by: Jaap Marcus <9754650+jaapmarcus@users.noreply.github.com>
Robert-Jan de Dreu 1 год назад
Родитель
Сommit
abd2cc3c2e

+ 35 - 35
web/src/app/System/HestiaApp.php

@@ -15,41 +15,6 @@ class HestiaApp {
 		@mkdir(self::TMPDIR_DOWNLOADS);
 		@mkdir(self::TMPDIR_DOWNLOADS);
 	}
 	}
 
 
-	public function run(string $cmd, $args, &$cmd_result = null): bool {
-		$cli_script = realpath(HESTIA_DIR_BIN . $cmd);
-		if (!str_starts_with((string) $cli_script, HESTIA_DIR_BIN)) {
-			$errstr = "$cmd is trying to traverse outside of " . HESTIA_DIR_BIN;
-			trigger_error($errstr);
-			throw new \Exception($errstr);
-		}
-		$cli_script = "/usr/bin/sudo " . quoteshellarg($cli_script);
-
-		$cli_arguments = "";
-		if (!empty($args) && is_array($args)) {
-			foreach ($args as $arg) {
-				$cli_arguments .= quoteshellarg((string) $arg) . " ";
-			}
-		} else {
-			$cli_arguments = quoteshellarg($args);
-		}
-
-		exec($cli_script . " " . $cli_arguments . " 2>&1", $output, $exit_code);
-
-		$result["code"] = $exit_code;
-		$result["args"] = $cli_arguments;
-		$result["raw"] = $output;
-		$result["text"] = implode(PHP_EOL, $output);
-		$result["json"] = json_decode($result["text"], true);
-		$cmd_result = (object) $result;
-		if ($exit_code > 0) {
-			//log error message in nginx-error.log
-			trigger_error($result["text"]);
-			//throw exception if command fails
-			throw new \Exception($result["text"]);
-		}
-		return $exit_code === 0;
-	}
-
 	public function runUser(string $cmd, $args, &$cmd_result = null): bool {
 	public function runUser(string $cmd, $args, &$cmd_result = null): bool {
 		if (!empty($args) && is_array($args)) {
 		if (!empty($args) && is_array($args)) {
 			array_unshift($args, $this->user());
 			array_unshift($args, $this->user());
@@ -364,4 +329,39 @@ class HestiaApp {
 	public function __destruct() {
 	public function __destruct() {
 		$this->cleanupTmpDir();
 		$this->cleanupTmpDir();
 	}
 	}
+
+	private function run(string $cmd, $args, &$cmd_result = null): bool {
+		$cli_script = realpath(HESTIA_DIR_BIN . $cmd);
+		if (!str_starts_with((string) $cli_script, HESTIA_DIR_BIN)) {
+			$errstr = "$cmd is trying to traverse outside of " . HESTIA_DIR_BIN;
+			trigger_error($errstr);
+			throw new \Exception($errstr);
+		}
+		$cli_script = "/usr/bin/sudo " . quoteshellarg($cli_script);
+
+		$cli_arguments = "";
+		if (!empty($args) && is_array($args)) {
+			foreach ($args as $arg) {
+				$cli_arguments .= quoteshellarg((string) $arg) . " ";
+			}
+		} else {
+			$cli_arguments = quoteshellarg($args);
+		}
+
+		exec($cli_script . " " . $cli_arguments . " 2>&1", $output, $exit_code);
+
+		$result["code"] = $exit_code;
+		$result["args"] = $cli_arguments;
+		$result["raw"] = $output;
+		$result["text"] = implode(PHP_EOL, $output);
+		$result["json"] = json_decode($result["text"], true);
+		$cmd_result = (object) $result;
+		if ($exit_code > 0) {
+			//log error message in nginx-error.log
+			trigger_error($cli_script . " " . $cli_arguments . " | " . $result["text"]);
+			//throw exception if command fails
+			throw new \Exception($result["text"]);
+		}
+		return $exit_code === 0;
+	}
 }
 }

+ 2 - 5
web/src/app/WebApp/Installers/DokuWiki/DokuWikiSetup.php

@@ -67,11 +67,8 @@ class DokuWikiSetup extends BaseSetup {
 		parent::setup($options);
 		parent::setup($options);
 
 
 		//check if ssl is enabled
 		//check if ssl is enabled
-		$this->appcontext->run(
-			"v-list-web-domain",
-			[$this->appcontext->user(), $this->domain, "json"],
-			$status,
-		);
+		$this->appcontext->runUser("v-list-web-domain", [$this->domain, "json"], $status);
+
 		$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
 		$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
 
 
 		$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain . "/";
 		$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain . "/";

+ 1 - 5
web/src/app/WebApp/Installers/Dolibarr/DolibarrSetup.php

@@ -58,11 +58,7 @@ class DolibarrSetup extends BaseSetup {
 			$status,
 			$status,
 		);
 		);
 
 
-		$this->appcontext->run(
-			"v-list-web-domain",
-			[$this->appcontext->user(), $this->domain, "json"],
-			$status,
-		);
+		$this->appcontext->runUser("v-list-web-domain", [$this->domain, "json"], $status);
 
 
 		$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? false : true;
 		$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? false : true;
 		$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain;
 		$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain;

+ 2 - 5
web/src/app/WebApp/Installers/Flarum/FlarumSetup.php

@@ -149,11 +149,8 @@ class FlarumSetup extends BaseSetup {
 		);
 		);
 
 
 		// POST install
 		// POST install
-		$this->appcontext->run(
-			"v-list-web-domain",
-			[$this->appcontext->user(), $this->domain, "json"],
-			$status,
-		);
+		$this->appcontext->runUser("v-list-web-domain", [$this->domain, "json"], $status);
+
 		$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
 		$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
 		$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain;
 		$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain;
 		$webPort = $sslEnabled ? "443" : "80";
 		$webPort = $sslEnabled ? "443" : "80";

+ 1 - 5
web/src/app/WebApp/Installers/MediaWiki/MediaWikiSetup.php

@@ -45,11 +45,7 @@ class MediaWikiSetup extends BaseSetup {
 		parent::setup($options);
 		parent::setup($options);
 
 
 		//check if ssl is enabled
 		//check if ssl is enabled
-		$this->appcontext->run(
-			"v-list-web-domain",
-			[$this->appcontext->user(), $this->domain, "json"],
-			$status,
-		);
+		$this->appcontext->runUser("v-list-web-domain", [$this->domain, "json"], $status);
 
 
 		if ($status->code !== 0) {
 		if ($status->code !== 0) {
 			throw new \Exception("Cannot list domain");
 			throw new \Exception("Cannot list domain");

+ 2 - 5
web/src/app/WebApp/Installers/OpenCart/OpenCartSetup.php

@@ -63,11 +63,8 @@ class OpenCartSetup extends BaseSetup {
 			$this->getDocRoot(".htaccess"),
 			$this->getDocRoot(".htaccess"),
 		]);
 		]);
 		#Check if SSL is enabled
 		#Check if SSL is enabled
-		$this->appcontext->run(
-			"v-list-web-domain",
-			[$this->appcontext->user(), $this->domain, "json"],
-			$status,
-		);
+		$this->appcontext->runUser("v-list-web-domain", [$this->domain, "json"], $status);
+
 		if ($status->code !== 0) {
 		if ($status->code !== 0) {
 			throw new \Exception("Cannot list domain");
 			throw new \Exception("Cannot list domain");
 		}
 		}

+ 2 - 5
web/src/app/WebApp/Installers/PrestaShop/PrestaShopSetup.php

@@ -49,11 +49,8 @@ class PrestaShopSetup extends BaseSetup {
 			$this->getDocRoot(),
 			$this->getDocRoot(),
 		);
 		);
 		//check if ssl is enabled
 		//check if ssl is enabled
-		$this->appcontext->run(
-			"v-list-web-domain",
-			[$this->appcontext->user(), $this->domain, "json"],
-			$status,
-		);
+		$this->appcontext->runUser("v-list-web-domain", [$this->domain, "json"], $status);
+
 		if ($status->code !== 0) {
 		if ($status->code !== 0) {
 			throw new \Exception("Cannot list domain");
 			throw new \Exception("Cannot list domain");
 		}
 		}

+ 1 - 5
web/src/app/WebApp/Installers/ThirtyBees/ThirtyBeesSetup.php

@@ -53,11 +53,7 @@ class ThirtyBeesSetup extends BaseSetup {
 
 
 		// Verificación del estado SSL del dominio
 		// Verificación del estado SSL del dominio
 		$status = null;
 		$status = null;
-		$this->appcontext->run(
-			"v-list-web-domain",
-			[$this->appcontext->user(), $this->domain, "json"],
-			$status,
-		);
+		$this->appcontext->runUser("v-list-web-domain", [$this->domain, "json"], $status);
 
 
 		if ($status->code !== 0) {
 		if ($status->code !== 0) {
 			throw new \Exception("No se puede listar el dominio");
 			throw new \Exception("No se puede listar el dominio");

+ 2 - 5
web/src/app/WebApp/Installers/WordPress/WordPressSetup.php

@@ -210,11 +210,8 @@ class WordpressSetup extends BaseSetup {
 			);
 			);
 		}
 		}
 
 
-		$this->appcontext->run(
-			"v-list-web-domain",
-			[$this->appcontext->user(), $this->domain, "json"],
-			$status,
-		);
+		$this->appcontext->runUser("v-list-web-domain", [$this->domain, "json"], $status);
+
 		$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
 		$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
 		$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain . "/";
 		$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain . "/";
 		$webPort = $sslEnabled ? "443" : "80";
 		$webPort = $sslEnabled ? "443" : "80";