From 8faa410d010fa3e3e38771fa09392552bcb03516 Mon Sep 17 00:00:00 2001
From: Mikhail Grigorev <sleuthhound@gmail.com>
Date: Thu, 23 Dec 2021 18:37:49 +0500
Subject: [PATCH] [DEV-2044] fixed possibility to view setup pages by
 non-superadmin if config already file exists

---
 .../include/classes/setup/CSetupWizard.php    | 65 +++++++++++++++----
 frontends/php/setup.php                       | 36 +++-------
 2 files changed, 62 insertions(+), 39 deletions(-)

diff --git a/frontends/php/include/classes/setup/CSetupWizard.php b/frontends/php/include/classes/setup/CSetupWizard.php
index a8313b04..cb4cf252 100644
--- a/frontends/php/include/classes/setup/CSetupWizard.php
+++ b/frontends/php/include/classes/setup/CSetupWizard.php
@@ -93,6 +93,8 @@ function doBack() {
 	}
 
 	protected function bodyToString($destroy = true) {
+		$step = $this->getStep();
+
 		$setup_left = (new CDiv([
 			(new CDiv())
 				->addClass(ZBX_STYLE_SIGNIN_LOGO)
@@ -114,18 +116,18 @@ protected function bodyToString($destroy = true) {
 			$cancel_button = null;
 		}
 
-		if (array_key_exists($this->getStep() + 1, $this->stage)) {
-			$next_button = new CSubmit('next['.$this->getStep().']', _('Next step'));
+		if (array_key_exists($step + 1, $this->stage)) {
+			$next_button = new CSubmit('next['.$step.']', _('Next step'));
 		}
 		else {
 			$next_button = new CSubmit($this->SHOW_RETRY_BUTTON ? 'retry' : 'finish', _('Finish'));
 		}
 
-		$back_button = (new CSubmit('back['.$this->getStep().']', _('Back')))
+		$back_button = (new CSubmit('back['.$step.']', _('Back')))
 			->addClass(ZBX_STYLE_BTN_ALT)
 			->addClass(ZBX_STYLE_FLOAT_LEFT);
 
-		if ($this->getStep() == 0 || $this->DISABLE_BACK_BUTTON) {
+		if ($step == 0 || $this->DISABLE_BACK_BUTTON) {
 			$back_button->setEnabled(false);
 		}
 
@@ -331,6 +333,20 @@ function stage4() {
 	}
 
 	function stage5() {
+		/*
+		 * Having non-super-admin authenticated at this step means:
+		 *   - Either the config file has been manually created by the user.
+		 *   - Or dealing with a spoofed session cookie.
+		 *
+		 * Since it is not possible to distinguish between the two, it's also impossible to validate the config file
+		 * and display any discrepancies with the configuration stored within the session.
+		 */
+		if (CWebUser::$data && CWebUser::getType() < USER_TYPE_SUPER_ADMIN) {
+			CSession::clear();
+
+			return $this->stageInstalled();
+		}
+
 		$this->setConfig('ZBX_CONFIG_FILE_CORRECT', true);
 
 		$config_file_name = APP::getInstance()->getRootDir().CConfigFile::CONFIG_FILE_PATH;
@@ -373,19 +389,30 @@ function stage5() {
 					new CTag('li', true, _s('Save it as "%1$s"', $config_file_name))
 				])
 			];
-		}
-		else {
-			$this->DISABLE_CANCEL_BUTTON = true;
-			$this->DISABLE_BACK_BUTTON = true;
 
-			$message_box = null;
-			$message = [
-				(new CTag('h1', true, _('Congratulations! You have successfully installed Zabbix frontend.')))
-					->addClass(ZBX_STYLE_GREEN),
-				new CTag('p', true, _s('Configuration file "%1$s" created.', $config_file_name))
+			return [
+				new CTag('h1', true, _('Install')),
+				(new CDiv([$message_box, $message]))->addClass(ZBX_STYLE_SETUP_RIGHT_BODY)
 			];
 		}
 
+		// Clear session after success install.
+		CSession::clear();
+
+		return $this->stageInstalled();
+	}
+
+	private function stageInstalled() {
+		$this->DISABLE_CANCEL_BUTTON = true;
+		$this->DISABLE_BACK_BUTTON = true;
+
+		$message_box = null;
+		$message = [
+			(new CTag('h1', true, _('Congratulations! You have successfully installed Zabbix frontend.')))
+				->addClass(ZBX_STYLE_GREEN),
+			new CTag('p', true, _s('Configuration file "%1$s" created.', ltrim(CConfigFile::CONFIG_FILE_PATH, '/')))
+		];
+
 		return [
 			new CTag('h1', true, _('Install')),
 			(new CDiv([$message_box, $message]))->addClass(ZBX_STYLE_SETUP_RIGHT_BODY)
@@ -451,6 +478,18 @@ function checkConnection() {
 	}
 
 	function eventHandler() {
+		/*
+		 * Having non-super-admin authenticated at this step means:
+		 *   - Either the config file has been manually created by the user.
+		 *   - Or dealing with a spoofed session cookie.
+		 *
+		 * Since it is not possible to distinguish between the two, skip data validation and prevent stage switching.
+		 * Any of either cases is only possible with 5th stage.
+		 */
+		if (CWebUser::$data && CWebUser::getType() < USER_TYPE_SUPER_ADMIN) {
+			return;
+		}
+
 		if (hasRequest('back') && array_key_exists($this->getStep(), getRequest('back'))) {
 			$this->doBack();
 		}
diff --git a/frontends/php/setup.php b/frontends/php/setup.php
index ee195213..9f0bc05d 100644
--- a/frontends/php/setup.php
+++ b/frontends/php/setup.php
@@ -58,31 +58,20 @@
 ];
 
 CSession::start();
-CSession::setValue('check_fields_result', check_fields($fields, false));
-if (!CSession::keyExists('step')) {
-	CSession::setValue('step', 0);
-}
 
-// if a guest or a non-super admin user is logged in
-if (CWebUser::$data && CWebUser::getType() < USER_TYPE_SUPER_ADMIN) {
-	// on the last step of the setup we always have a guest user logged in;
-	// when he presses the "Finish" button he must be redirected to the login screen
-	if (CWebUser::isGuest() && CSession::getValue('step') == 5 && hasRequest('finish')) {
-		CSession::clear();
-		redirect('index.php');
-	}
-	// the guest user can also view the last step of the setup
-	// all other user types must not have access to the setup
-	elseif (!(CWebUser::isGuest() && CSession::getValue('step') == 5)) {
-		access_deny(ACCESS_DENY_PAGE);
-	}
-}
-// if a super admin or a non-logged in user presses the "Finish" or "Login" button - redirect him to the login screen
-elseif (hasRequest('cancel') || hasRequest('finish')) {
+$check_fields_result = check_fields($fields, false);
+
+if (hasRequest('cancel') || hasRequest('finish')) {
 	CSession::clear();
 	redirect('index.php');
 }
 
+if (CWebUser::$data && CWebUser::getType() < USER_TYPE_SUPER_ADMIN && CSession::getValue('step') != 5) {
+	access_deny(ACCESS_DENY_PAGE);
+}
+
+CSession::setValue('check_fields_result', $check_fields_result);
+
 $theme = CWebUser::$data ? getUserTheme(CWebUser::$data) : ZBX_DEFAULT_THEME;
 
 DBclose();
@@ -92,11 +81,6 @@
  */
 $ZBX_SETUP_WIZARD = new CSetupWizard();
 
-// if init fails due to missing configuration, set user as guest with default en_GB language
-if (!CWebUser::$data) {
-	CWebUser::setDefault();
-}
-
 // page title
 (new CPageHeader(_('Installation')))
 	->addCssFile('assets/styles/'.CHtml::encode($theme).'.css')
@@ -118,7 +102,7 @@
 $sub_footer = (new CDiv(['Licensed under ', $link]))->addClass(ZBX_STYLE_SIGNIN_LINKS);
 
 (new CTag('body', true, [(new CTag('main', true, [$ZBX_SETUP_WIZARD, $sub_footer])), makePageFooter()]))
-	->setAttribute('lang', CWebUser::getLang())
+	->setAttribute('lang', 'en_gb')
 	->show();
 ?>
 </html>