diff --git a/CHANGELOG.md b/CHANGELOG.md index bdb7ae655..ab0365a17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ This file is a running track of new features and fixes to each version of the pa This project follows [Semantic Versioning](http://semver.org) guidelines. +## v0.7.9 (Derelict Dermodactylus) +### Fixed +* Fixes a two-factor authentication bypass present in the password reset process for an account. + ## v0.7.8 (Derelict Dermodactylus) ### Added * Nodes can now be put into maintenance mode to deny access to servers temporarily. diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 226958416..d1f21994f 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -2,8 +2,14 @@ namespace Pterodactyl\Http\Controllers\Auth; +use Illuminate\Support\Str; +use Prologue\Alerts\AlertsMessageBag; +use Illuminate\Contracts\Hashing\Hasher; +use Illuminate\Auth\Events\PasswordReset; +use Illuminate\Contracts\Events\Dispatcher; use Pterodactyl\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ResetsPasswords; +use Pterodactyl\Contracts\Repository\UserRepositoryInterface; class ResetPasswordController extends Controller { @@ -16,6 +22,47 @@ class ResetPasswordController extends Controller */ public $redirectTo = '/'; + /** + * @var bool + */ + protected $hasTwoFactor = false; + + /** + * @var \Prologue\Alerts\AlertsMessageBag + */ + private $alerts; + + /** + * @var \Illuminate\Contracts\Events\Dispatcher + */ + private $dispatcher; + + /** + * @var \Illuminate\Contracts\Hashing\Hasher + */ + private $hasher; + + /** + * @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface + */ + private $userRepository; + + /** + * ResetPasswordController constructor. + * + * @param \Prologue\Alerts\AlertsMessageBag $alerts + * @param \Illuminate\Contracts\Events\Dispatcher $dispatcher + * @param \Illuminate\Contracts\Hashing\Hasher $hasher + * @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $userRepository + */ + public function __construct(AlertsMessageBag $alerts, Dispatcher $dispatcher, Hasher $hasher, UserRepositoryInterface $userRepository) + { + $this->alerts = $alerts; + $this->dispatcher = $dispatcher; + $this->hasher = $hasher; + $this->userRepository = $userRepository; + } + /** * Return the rules used when validating password reset. * @@ -29,4 +76,49 @@ class ResetPasswordController extends Controller 'password' => 'required|confirmed|min:8', ]; } + + /** + * Reset the given user's password. If the user has two-factor authentication enabled on their + * account do not automatically log them in. In those cases, send the user back to the login + * form with a note telling them their password was changed and to log back in. + * + * @param \Illuminate\Contracts\Auth\CanResetPassword|\Pterodactyl\Models\User $user + * @param string $password + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + */ + protected function resetPassword($user, $password) + { + $user = $this->userRepository->update($user->id, [ + 'password' => $this->hasher->make($password), + $user->getRememberTokenName() => Str::random(60), + ]); + + $this->dispatcher->dispatch(new PasswordReset($user)); + + // If the user is not using 2FA log them in, otherwise skip this step and force a + // fresh login where they'll be prompted to enter a token. + if (! $user->use_totp) { + $this->guard()->login($user); + } + + $this->hasTwoFactor = $user->use_totp; + } + + /** + * Get the response for a successful password reset. + * + * @param string $response + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + protected function sendResetResponse($response) + { + if ($this->hasTwoFactor) { + $this->alerts->success('Your password was successfully updated. Please log in to continue.')->flash(); + } + + return redirect($this->hasTwoFactor ? route('auth.login') : $this->redirectPath()) + ->with('status', trans($response)); + } } diff --git a/config/app.php b/config/app.php index 9acaee54e..d7699ee8b 100644 --- a/config/app.php +++ b/config/app.php @@ -9,7 +9,7 @@ return [ | change this value if you are not maintaining your own internal versions. */ - 'version' => '0.7.8', + 'version' => '0.7.9', /* |-------------------------------------------------------------------------- diff --git a/resources/lang/de/strings.php b/resources/lang/de/strings.php index 2e2f2a751..299a7d67e 100644 --- a/resources/lang/de/strings.php +++ b/resources/lang/de/strings.php @@ -48,7 +48,7 @@ return [ 'select_none' => 'Alles abwählen', 'alias' => 'Alias', 'primary' => 'Primär', - 'make_primary' => 'Primät machen', + 'make_primary' => 'Primär machen', 'none' => 'Nichts', 'cancel' => 'Abbrechen', 'created_at' => 'Erstellt am',