/** * @return void */ public static function UpdateConnectionToken() { $sKey = 'rltoken'; $sToken = \RainLoop\Utils::GetCookie($sKey, ''); if (!empty($sToken)) { \RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30, '/', null, null, true); } }
/** * @param string $sEmail * @param string $sPassword * @param string $sSignMeToken = '' * @param string $sAdditionalCode = '' * @param string $bAdditionalCodeSignMe = false * * @return \RainLoop\Model\Account * @throws \RainLoop\Exceptions\ClientException */ public function LoginProcess(&$sEmail, &$sPassword, $sSignMeToken = '', $sAdditionalCode = '', $bAdditionalCodeSignMe = false) { $this->Plugins()->RunHook('filter.login-credentials.step-1', array(&$sEmail, &$sPassword)); $sEmail = \MailSo\Base\Utils::StrToLowerIfAscii(\MailSo\Base\Utils::Trim($sEmail)); if (false === \strpos($sEmail, '@')) { $this->Logger()->Write('The email address "' . $sEmail . '" is not complete', \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); if (false === \strpos($sEmail, '@') && !!$this->Config()->Get('login', 'determine_user_domain', false)) { $sUserHost = \trim($this->Http()->GetHost(false, true, true)); $this->Logger()->Write('Determined user domain: ' . $sUserHost, \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); $bAdded = false; $iLimit = 14; $aDomainParts = \explode('.', $sUserHost); $oDomainProvider = $this->DomainProvider(); while (0 < \count($aDomainParts) && 0 < $iLimit) { $sLine = \trim(\implode('.', $aDomainParts), '. '); $oDomain = $oDomainProvider->Load($sLine, false); if ($oDomain && $oDomain instanceof \RainLoop\Model\Domain) { $bAdded = true; $this->Logger()->Write('Check "' . $sLine . '": OK (' . $sEmail . ' > ' . $sEmail . '@' . $sLine . ')', \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); $sEmail = $sEmail . '@' . $sLine; break; } else { $this->Logger()->Write('Check "' . $sLine . '": NO', \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); } \array_shift($aDomainParts); $iLimit--; } if (!$bAdded) { $sLine = $sUserHost; $oDomain = $oDomainProvider->Load($sLine, true); if ($oDomain && $oDomain instanceof \RainLoop\Model\Domain) { $bAdded = true; $this->Logger()->Write('Check "' . $sLine . '" with wildcard: OK (' . $sEmail . ' > ' . $sEmail . '@' . $sLine . ')', \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); $sEmail = $sEmail . '@' . $sLine; } else { $this->Logger()->Write('Check "' . $sLine . '" with wildcard: NO', \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); } } if (!$bAdded) { $this->Logger()->Write('Domain was not found!', \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); } } $sDefDomain = \trim($this->Config()->Get('login', 'default_domain', '')); if (false === \strpos($sEmail, '@') && 0 < \strlen($sDefDomain)) { $this->Logger()->Write('Default domain "' . $sDefDomain . '" was used. (' . $sEmail . ' > ' . $sEmail . '@' . $sDefDomain . ')', \MailSo\Log\Enumerations\Type::INFO, 'LOGIN'); $sEmail = $sEmail . '@' . $sDefDomain; } } $this->Plugins()->RunHook('filter.login-credentials.step-2', array(&$sEmail, &$sPassword)); if (false === \strpos($sEmail, '@') || 0 === \strlen($sPassword)) { $this->loginErrorDelay(); throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument); } $this->Logger()->AddSecret($sPassword); $sLogin = $sEmail; $this->Plugins()->RunHook('filter.login-credentials', array(&$sEmail, &$sLogin, &$sPassword)); $this->Logger()->AddSecret($sPassword); $this->Plugins()->RunHook('event.login-pre-login-provide', array()); $oAccount = null; try { $oAccount = $this->LoginProvide($sEmail, $sLogin, $sPassword, $sSignMeToken, true); if (!$oAccount instanceof \RainLoop\Model\Account) { throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError); } $this->Plugins()->RunHook('event.login-post-login-provide', array(&$oAccount)); if (!$oAccount instanceof \RainLoop\Model\Account) { throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError); } } catch (\Exception $oException) { $this->loginErrorDelay(); $this->LoggerAuthHelper($oAccount); throw $oException; } // Two factor auth if ($this->TwoFactorAuthProvider()->IsActive()) { $aData = $this->getTwoFactorInfo($oAccount); if ($aData && isset($aData['IsSet'], $aData['Enable']) && !empty($aData['Secret']) && $aData['IsSet'] && $aData['Enable']) { $sSecretHash = \md5(APP_SALT . $aData['Secret'] . \RainLoop\Utils::Fingerprint()); $sSecretCookieHash = \RainLoop\Utils::GetCookie(self::AUTH_TFA_SIGN_ME_TOKEN_KEY, ''); if (empty($sSecretCookieHash) || $sSecretHash !== $sSecretCookieHash) { $sAdditionalCode = \trim($sAdditionalCode); if (empty($sAdditionalCode)) { $this->Logger()->Write('TFA: Required Code for ' . $oAccount->ParentEmailHelper() . ' account.'); $this->LoggerAuthHelper($oAccount); throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AccountTwoFactorAuthRequired); } else { $this->Logger()->Write('TFA: Verify Code for ' . $oAccount->ParentEmailHelper() . ' account.'); $bGood = false; if (6 < \strlen($sAdditionalCode) && !empty($aData['BackupCodes'])) { $aBackupCodes = \explode(' ', \trim(\preg_replace('/[^\\d]+/', ' ', $aData['BackupCodes']))); $bGood = \in_array($sAdditionalCode, $aBackupCodes); if ($bGood) { $this->removeBackupCodeFromTwoFactorInfo($oAccount->ParentEmailHelper(), $sAdditionalCode); } } if ($bAdditionalCodeSignMe) { \RainLoop\Utils::SetCookie(self::AUTH_TFA_SIGN_ME_TOKEN_KEY, $sSecretHash, \time() + 60 * 60 * 24 * 14); } if (!$bGood && !$this->TwoFactorAuthProvider()->VerifyCode($aData['Secret'], $sAdditionalCode)) { $this->loginErrorDelay(); $this->LoggerAuthHelper($oAccount); throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AccountTwoFactorAuthError); } } } } } try { $this->CheckMailConnection($oAccount, true); } catch (\Exception $oException) { $this->loginErrorDelay(); throw $oException; } return $oAccount; }