diff --git a/application/logindefault.class.inc.php b/application/logindefault.class.inc.php index 26307cce1..abe8bfbef 100644 --- a/application/logindefault.class.inc.php +++ b/application/logindefault.class.inc.php @@ -119,6 +119,11 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte protected function OnConnected(&$iErrorCode) { Session::Unset('login_temp_auth_user'); + if (is_null(UserRights::GetUserObject())){ + //N°7085 avoid infinite loop + IssueLog::Error("No user logged in. exit"); + exit(-1); + } return LoginWebPage::LOGIN_FSM_CONTINUE; } @@ -134,4 +139,4 @@ class LoginDefaultAfter extends AbstractLoginFSMExtension implements iLogoutExte } } } -} \ No newline at end of file +} diff --git a/core/config.class.inc.php b/core/config.class.inc.php index ae020cf04..8f1a295a9 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -2369,6 +2369,24 @@ class Config $this->m_sAllowedLoginTypes = implode('|', $aAllowedLoginTypes); } + /** + * @since 2.7.11 N°7085 + * Add login mode if not configured already + * @param string $sLoginMode + * + * @return void + */ + public function AddAllowedLoginTypes($sLoginMode) + { + $aAllowedLoginTypes = $this->GetAllowedLoginTypes(); + if (in_array($sLoginMode, $aAllowedLoginTypes)){ + return; + } + + $aAllowedLoginTypes[] = $sLoginMode; + $this->SetAllowedLoginTypes($aAllowedLoginTypes); + } + public function SetExternalAuthenticationVariable($sExtAuthVariable) { $this->m_sExtAuthVariable = $sExtAuthVariable; diff --git a/tests/php-unit-tests/unitary-tests/application/LoginTest.php b/tests/php-unit-tests/unitary-tests/application/LoginTest.php new file mode 100644 index 000000000..b2e12358e --- /dev/null +++ b/tests/php-unit-tests/unitary-tests/application/LoginTest.php @@ -0,0 +1,70 @@ +sConfigPath = MetaModel::GetConfig()->GetLoadedFile(); + $this->sConfigTmpBackupFile = tempnam(sys_get_temp_dir(), "config_"); + file_put_contents($this->sConfigTmpBackupFile, file_get_contents($this->sConfigPath)); + + $oConfig = new \Config($this->sConfigPath); + $this->sLoginMode = "unimplemented_loginmode"; + $oConfig->AddAllowedLoginTypes($this->sLoginMode); + + @chmod($this->sConfigPath, 0770); + $oConfig->WriteToFile(); + @chmod($this->sConfigPath, 0440); + } + + protected function tearDown(): void { + if (! is_null($this->sConfigTmpBackupFile) && is_file($this->sConfigTmpBackupFile)){ + //put config back + @chmod($this->sConfigPath, 0770); + file_put_contents($this->sConfigPath, file_get_contents($this->sConfigTmpBackupFile)); + @chmod($this->sConfigPath, 0440); + @unlink($this->sConfigTmpBackupFile); + } + parent::tearDown(); + } + + public function testLoginInfiniteLoopFix() { + $iTimeStamp = microtime(true); + $sOutput = $this->CallItopUrlByCurl(sprintf("/pages/UI.php?login_mode=%s", $this->sLoginMode)); + $iElapsedInMs = (microtime(true) - $iTimeStamp) * 1000; + $sMaxExecutionInS = 1; + $this->assertTrue($iElapsedInMs < $sMaxExecutionInS * 1000, "iTop answered in $iElapsedInMs ms. it should do it in less than $sMaxExecutionInS seconds (max_execution_time)"); + $this->assertFalse(strpos($sOutput, "Fatal error"), "no fatal error due to max execution time should be returned" . $sOutput); + } + + protected function CallItopUrlByCurl($sUri, ?array $aPostFields=[]){ + $ch = curl_init(); + + $sUrl = MetaModel::GetConfig()->Get('app_root_url') . "/$sUri"; + curl_setopt($ch, CURLOPT_URL, $sUrl); + if (0 !== sizeof($aPostFields)){ + curl_setopt($ch, CURLOPT_POST, 1);// set post data to true + curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostFields); + } + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $sOutput = curl_exec($ch); + curl_close ($ch); + + return $sOutput; + } +}