passwordResetter = $passwordResetter; if (empty($auth)) { $auth = StaticContainer::get('Piwik\Auth'); } $this->auth = $auth; if (empty($passwordVerify)) { $passwordVerify = StaticContainer::get('Piwik\Plugins\Login\PasswordVerifier'); } $this->passwordVerify = $passwordVerify; if (empty($sessionInitializer)) { $sessionInitializer = new \Piwik\Session\SessionInitializer(); } $this->sessionInitializer = $sessionInitializer; if (empty($bruteForceDetection)) { $bruteForceDetection = StaticContainer::get('Piwik\Plugins\Login\Security\BruteForceDetection'); } $this->bruteForceDetection = $bruteForceDetection; if (empty($systemSettings)) { $systemSettings = StaticContainer::get('Piwik\Plugins\Login\SystemSettings'); } $this->systemSettings = $systemSettings; } /** * Default action * * @return string */ function index() { return $this->login(); } /** * Login form * * @param string $messageNoAccess Access error message * @param bool $infoMessage * @internal param string $currentUrl Current URL * @return string */ function login($messageNoAccess = null, $infoMessage = false) { $form = new FormLogin(); if ($form->validate()) { $nonce = $form->getSubmitValue('form_nonce'); if (Nonce::verifyNonce('Login.login', $nonce)) { $loginOrEmail = $form->getSubmitValue('form_login'); $login = $this->getLoginFromLoginOrEmail($loginOrEmail); $password = $form->getSubmitValue('form_password'); try { $this->authenticateAndRedirect($login, $password); } catch (Exception $e) { $messageNoAccess = $e->getMessage(); } } else { $messageNoAccess = $this->getMessageExceptionNoAccess(); } } if ($messageNoAccess) { http_response_code(403); } $view = new View('@Login/login'); $view->AccessErrorString = $messageNoAccess; $view->infoMessage = nl2br($infoMessage); $view->addForm($form); $this->configureView($view); self::setHostValidationVariablesView($view); return $view->render(); } private function getLoginFromLoginOrEmail($loginOrEmail) { $model = new UsersModel(); if (!$model->userExists($loginOrEmail)) { $user = $model->getUserByEmail($loginOrEmail); if (!empty($user)) { return $user['login']; } } return $loginOrEmail; } /** * Configure common view properties * * @param View $view */ protected function configureView($view) { $this->setBasicVariablesNoneAdminView($view); $view->linkTitle = Piwik::getRandomTitle(); // crsf token: don't trust the submitted value; generate/fetch it from session data $view->nonce = Nonce::getNonce('Login.login'); } public function confirmPassword() { Piwik::checkUserIsNotAnonymous(); Piwik::checkUserHasSomeViewAccess(); if (!$this->passwordVerify->hasPasswordVerifyBeenRequested()) { throw new Exception('Not available'); } if (!Url::isValidHost()) { throw new Exception("Cannot confirm password with untrusted hostname!"); } $nonceKey = 'confirmPassword'; $messageNoAccess = ''; if (!empty($_POST)) { $nonce = Common::getRequestVar('nonce', null, 'string', $_POST); $password = Common::getRequestVar('password', null, 'string', $_POST); if ($password) { $password = Common::unsanitizeInputValue($password); } if (!Nonce::verifyNonce($nonceKey, $nonce)) { $messageNoAccess = $this->getMessageExceptionNoAccess(); } elseif ($this->passwordVerify->isPasswordCorrect(Piwik::getCurrentUserLogin(), $password)) { $this->passwordVerify->setPasswordVerifiedCorrectly(); return; } else { $messageNoAccess = Piwik::translate('Login_WrongPasswordEntered'); } } return $this->renderTemplate('confirmPassword', array( 'nonce' => Nonce::getNonce($nonceKey), 'AccessErrorString' => $messageNoAccess )); } /** * Form-less login * @see how to use it on http://piwik.org/faq/how-to/#faq_30 * @throws Exception * @return void */ function logme() { $password = Common::getRequestVar('password', null, 'string'); $login = Common::getRequestVar('login', null, 'string'); if (Piwik::hasTheUserSuperUserAccess($login)) { throw new Exception(Piwik::translate('Login_ExceptionInvalidSuperUserAccessAuthenticationMethod', array("logme"))); } $currentUrl = 'index.php'; if ($this->idSite) { $currentUrl .= '?idSite=' . $this->idSite; } $urlToRedirect = Common::getRequestVar('url', $currentUrl, 'string'); $urlToRedirect = Common::unsanitizeInputValue($urlToRedirect); $this->authenticateAndRedirect($login, $password, $urlToRedirect, $passwordHashed = true); } public function bruteForceLog() { Piwik::checkUserHasSuperUserAccess(); return $this->renderTemplate('bruteForceLog', array( 'blockedIps' => $this->bruteForceDetection->getCurrentlyBlockedIps(), 'blacklistedIps' => $this->systemSettings->blacklistedBruteForceIps->getValue() )); } /** * Error message shown when an AJAX request has no access * * @param string $errorMessage * @return string */ public function ajaxNoAccess($errorMessage) { return sprintf( '
%s: %s
force_ssl=1', '
[General]', ) ); } return $message; } /** * Reset password action. Stores new password as hash and sends email * to confirm use. * */ function resetPassword() { $infoMessage = null; $formErrors = null; $form = new FormResetPassword(); if ($form->validate()) { $nonce = $form->getSubmitValue('form_nonce'); if (Nonce::verifyNonce('Login.login', $nonce)) { $formErrors = $this->resetPasswordFirstStep($form); if (empty($formErrors)) { $infoMessage = Piwik::translate('Login_ConfirmationLinkSent'); } } else { $formErrors = array($this->getMessageExceptionNoAccess()); } } else { // if invalid, display error $formData = $form->getFormData(); $formErrors = $formData['errors']; } $view = new View('@Login/resetPassword'); $view->infoMessage = $infoMessage; $view->formErrors = $formErrors; return $view->render(); } /** * Saves password reset info and sends confirmation email. * * @param QuickForm2 $form * @return array Error message(s) if an error occurs. */ protected function resetPasswordFirstStep($form) { $loginMail = $form->getSubmitValue('form_login'); $password = $form->getSubmitValue('form_password'); try { $this->passwordResetter->initiatePasswordResetProcess($loginMail, $password); } catch (Exception $ex) { Log::debug($ex); return array($ex->getMessage()); } return null; } /** * Password reset confirmation action. Finishes the password reset process. * Users visit this action from a link supplied in an email. */ public function confirmResetPassword() { if (!Url::isValidHost()) { throw new Exception("Cannot confirm reset password with untrusted hostname!"); } $errorMessage = null; $passwordHash = null; $login = Common::getRequestVar('login'); $resetToken = Common::getRequestVar('resetToken'); try { $passwordHash = $this->passwordResetter->checkValidConfirmPasswordToken($login, $resetToken); } catch (Exception $ex) { Log::debug($ex); $errorMessage = $ex->getMessage(); } if (!empty($errorMessage)) { return $this->login($errorMessage); } if (!empty($_POST['nonce']) && !empty($_POST['mtmpasswordconfirm']) && !empty($resetToken) && !empty($login) && !empty($passwordHash) && empty($errorMessage)) { Nonce::checkNonce(self::NONCE_CONFIRMRESETPASSWORD, $_POST['nonce']); if ($this->passwordResetter->doesResetPasswordHashMatchesPassword($_POST['mtmpasswordconfirm'], $passwordHash)) { $this->passwordResetter->setHashedPasswordForLogin($login, $passwordHash); return $this->resetPasswordSuccess(); } else { $errorMessage = Piwik::translate('Login_ConfirmPasswordResetWrongPassword'); } } $nonce = Nonce::getNonce(self::NONCE_CONFIRMRESETPASSWORD); return $this->renderTemplateAs('confirmResetPassword', array( 'nonce' => $nonce, 'errorMessage' => $errorMessage ), 'basic'); } /** * The action used after a password is successfully reset. Displays the login * screen with an extra message. A separate action is used instead of returning * the HTML in confirmResetPassword so the resetToken won't be in the URL. */ public function resetPasswordSuccess() { $_POST = array(); // prevent showing error message username and password is missing return $this->login($errorMessage = null, $infoMessage = Piwik::translate('Login_PasswordChanged')); } /** * Clear session information * * @return void */ public static function clearSession() { $sessionFingerprint = new Session\SessionFingerprint(); $sessionFingerprint->clear(); Session::expireSessionCookie(); } /** * Logout current user * * @return void */ public function logout() { Piwik::postEvent('Login.logout', array(Piwik::getCurrentUserLogin())); self::clearSession(); $logoutUrl = @Config::getInstance()->General['login_logout_url']; if (empty($logoutUrl)) { Piwik::redirectToModule('CoreHome'); } else { Url::redirectToUrl($logoutUrl); } } }