コード例 #1
0
ファイル: Account.php プロジェクト: nsdown/rainloop-webmail
 /**
  * @return string
  */
 public function GetAuthTokenQ()
 {
     return \RainLoop\Utils::EncodeKeyValuesQ(array('token', $this->sEmail, $this->sLogin, $this->sPassword, \RainLoop\Utils::Fingerprint(), $this->sSignMeToken, $this->sParentEmail, \RainLoop\Utils::GetShortToken(), $this->sProxyAuthUser, $this->sProxyAuthPassword, 0));
 }
コード例 #2
0
 /**
  * @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;
 }