diff --git a/app/utils.php b/app/utils.php
index ed221a4..a087f66 100644
--- a/app/utils.php
+++ b/app/utils.php
@@ -38,10 +38,10 @@ function htmlToPlain($message): string {
return $messageNew;
}
-function sendMail($message, $subject, $title, $preheader): bool {
- include_once('../lib/phpmailer/Exception.php');
- include_once('../lib/phpmailer/PHPMailer.php');
- include_once('../lib/phpmailer/SMTP.php');
+function sendMail($email, $message, $subject, $title, $preheader): bool {
+ include_once('lib/phpmailer/Exception.php');
+ include_once('lib/phpmailer/PHPMailer.php');
+ include_once('lib/phpmailer/SMTP.php');
include_once('app/HTML.php');
global $RUNTIME;
@@ -53,6 +53,7 @@ function sendMail($message, $subject, $title, $preheader): bool {
$mailer->Port = $RUNTIME['SMTP']['PORT'];
$mailer->Username = $RUNTIME['SMTP']['ADDRESS'];
$mailer->Password = $RUNTIME['SMTP']['PASS'];
+ $mailer->SMTPAuth = true;
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mailer->setFrom($RUNTIME['SMTP']['ADDRESS'], $RUNTIME['SMTP']['NAME']);
@@ -61,7 +62,7 @@ function sendMail($message, $subject, $title, $preheader): bool {
$mailer->isHTML(true);
$mailer->Subject = $subject;
$mailHtml = new HTML();
- $mailHtml->importHTML("email.html");
+ $mailHtml->importHTML("mail.html");
$mailHtml->setHTMLTitle($title);
$mailHtml->ReplaceLayoutInhalt('%%MESSAGE%%', $message);
$mailHtml->ReplaceLayoutInhalt('%%PREHEADER%%', $preheader);
diff --git a/pages/forgot.php b/pages/forgot.php
index 940ee1c..3ce4c7a 100644
--- a/pages/forgot.php
+++ b/pages/forgot.php
@@ -15,21 +15,25 @@
if(!$validator->isValid($_POST)) {
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', 'Bitte gebe deinen Benutzernamen (Vor- und Nachname) und die dazugehörige E-Mail-Adresse ein');
$HTML->ReplaceLayoutInhalt('%%MESSAGECOLOR%%', 'red');
+ $HTML->build();
+ echo $HTML->ausgabe();
}
else {
$nameParts = explode(" ", $_POST['username']);
$email = strtolower(trim($_POST['email']));
- $getAccount = $RUNTIME['pdo']->prepare('SELECT Email,FirstName,LastName,PrincipalID FROM UserAccounts WHERE FirstName = ? AND LastName = ? AND Email = ?');
+ $getAccount = $RUNTIME['PDO']->prepare('SELECT Email,FirstName,LastName,PrincipalID FROM UserAccounts WHERE FirstName = ? AND LastName = ? AND Email = ?');
$getAccount->execute([trim($nameParts[0]), trim($nameParts[1]), $email]);
$validRequest = $getAccount->rowCount() == 1;
+ $uuid;
+ $name;
if($res = $getAccount->fetch()) {
$email = $res['Email'];
$uuid = $res['PrincipalID'];
$name = $res['FirstName'].' '.$res['LastName'];
}
- foreach($blockedDomains as $domain) {
+ foreach($RUNTIME['RESET_BLOCKED_DOMAINS'] as $domain) {
if(str_ends_with($email, $domain)) {
$validRequest = false;
}
@@ -42,7 +46,7 @@
fastcgi_finish_request();
if($validRequest) {
- $getReqTime = $RUNTIME['pdo']->prepare('SELECT RequestTime FROM PasswordResetTokens WHERE PrincipalID=?');
+ $getReqTime = $RUNTIME['PDO']->prepare('SELECT RequestTime FROM PasswordResetTokens WHERE PrincipalID=?');
$getReqTime->execute([$uuid]);
if(($res = $getReqTime->fetch()) && time() - $res['RequestTime'] < 900) {
return;
@@ -50,10 +54,10 @@
require_once 'app/utils.php';
$token = generateToken(32);
- $setToken = $RUNTIME['pdo']->prepare('REPLACE INTO PasswordResetTokens(PrincipalID,Token,RequestTime) VALUES(?,?,?)');
+ $setToken = $RUNTIME['PDO']->prepare('REPLACE INTO PasswordResetTokens(PrincipalID,Token,RequestTime) VALUES(?,?,?)');
$setToken->execute([$uuid, $token, time()]);
- sendMail(str_replace('%%NAME%%', $name, str_replace('%%RESET_LINK%%', 'https://'.$RUNTIME['DOMAIN'].'/index.php?page=reset-password&token='.$token, MESSAGE)), "Zurücksetzung des Passworts für ".$name, 'Dein Passwort zurücksetzen', 'Folge diesen Anweisungen, um ein neues Passwort für deinen 4Creative-Account festzulegen');
+ sendMail($email, str_replace('%%NAME%%', $name, str_replace('%%RESET_LINK%%', 'https://'.$RUNTIME['DOMAIN'].'/index.php?page=reset-password&token='.$token, MESSAGE)), "Zurücksetzung des Passworts für ".$name, 'Dein Passwort zurücksetzen', 'Folge diesen Anweisungen, um ein neues Passwort für deinen 4Creative-Account festzulegen');
}
}
}
diff --git a/pages/reset-password.php b/pages/reset-password.php
index 0d0b30d..6603b00 100644
--- a/pages/reset-password.php
+++ b/pages/reset-password.php
@@ -1,19 +1,27 @@
das Passwort für deinen 4Creative-Account wurde soeben über die Funktion "Passwort vergessen" geändert.
Solltest du diese Änderung nicht selbst durchgeführt haben, wende dich bitte umgehend per E-Mail (info@4creative.net) oder Discord (@ikeytan) an uns.';
+ const TOKEN_INVALID = 'Dieser Link zur Passwortzurücksetzung ist nicht gültig. Bitte klicke oder kopiere den Link aus der E-Mail, die du erhalten hast.';
+ const TOKEN_EXPIRED = 'Dein Link zur Passwortzurücksetzung ist abgelaufen. Klicke hier, um eine neue Anfrage zu senden.';
- function displayTokenError() {
+ function displayTokenError($message) {
$HTML = new HTML();
$HTML->importHTML("error.html");
- $HTML->ReplaceLayoutInhalt('%%MESSAGE%%', 'Dieser Link zur Passwortzurücksetzung ist nicht gültig. Bitte klicke oder kopiere den Link aus der E-Mail, die du erhalten hast.');
+ $HTML->ReplaceLayoutInhalt('%%MESSAGE%%', $message);
$HTML->build();
+ echo $HTML->ausgabe();
exit();
}
function displayPage($err) {
+ if(!isset($_GET['token']) || !preg_match('/^[a-z0-9A-Z]{32}$/', $_GET['token'])) {
+ displayTokenError(TOKEN_INVALID);
+ }
+
$HTML = new HTML();
$HTML->setHTMLTitle("");
$HTML->importHTML("reset-password.html");
$HTML->ReplaceLayoutInhalt('%%MESSAGE%%', $err);
+ $HTML->ReplaceLayoutInhalt('%%RESET_TOKEN%%', htmlspecialchars($_GET['token']));
$HTML->build();
echo $HTML->ausgabe();
exit();
@@ -36,16 +44,29 @@
displayPage('Dein Passwort muss mindestens '.$RUNTIME['PASSWORD_MIN_LENGTH'].' Zeichen lang sein.');
}
- $getUuid = $RUNTIME['PDO']->prepare('SELECT PrincipalID,FirstName,LastName FROM PasswordResetTokens JOIN UserAccounts ON PasswordResetTokens.PrincipalID = PasswordResetTokens.PrincipalID WHERE Token = ?');
- if($getUuid->rowCount() == 0) {
- displayTokenError();
+ $getReq = $RUNTIME['PDO']->prepare('SELECT UserAccounts.PrincipalID AS UUID,FirstName,LastName,Email,Token,RequestTime FROM PasswordResetTokens JOIN UserAccounts ON UserAccounts.PrincipalID = PasswordResetTokens.PrincipalID WHERE Token = ?');
+ $getReq->execute([$_POST['resetToken']]);
+ if($getReq->rowCount() == 0) {
+ displayTokenError(TOKEN_INVALID);
}
- $res = $getUuid->fetch();
- $uuid = $res['PrincipalID'];
+ $res = $getReq->fetch();
+
+ if(!hash_equals($res['Token'], $_POST['resetToken'])) {
+ displayTokenError(TOKEN_INVALID);
+ }
+
+ $uuid = $res['UUID'];
$name = $res['FirstName'].' '.$res['LastName'];
- $getToken = $RUNTIME['PDO']->prepare('DELETE FROM PasswordResetTokens WHERE Token = ?');
- $getToken->execute([$_POST['resetToken']]);
+ $getToken = $RUNTIME['PDO']->prepare('DELETE FROM PasswordResetTokens WHERE PrincipalID = ? AND Token = ?');
+ $getToken->execute([$uuid, $_POST['resetToken']]);
+ if($getToken->rowCount() == 0) {
+ displayTokenError(TOKEN_INVALID);
+ }
+
+ if(time() - $res['RequestTime'] > 86400) {
+ displayTokenError(TOKEN_EXPIRED);
+ }
$salt = bin2hex(random_bytes(16));
$hash = md5(md5(trim($_POST['password'])).':'.$salt);
@@ -57,7 +78,7 @@
$_SESSION['loginMessageColor'] = 'darkgreen';
require_once 'app/utils.php';
- sendMail(str_replace('%%NAME%%', $name, MESSAGE), 'Passwort für '.$name.' zurückgesetzt', 'Passwort geändert', 'Das Passwort für deinen 4Creative-Account wurde soeben zurückgesetzt');
+ sendMail($res['Email'], str_replace('%%NAME%%', $name, MESSAGE), 'Passwort für '.$name.' zurückgesetzt', 'Passwort geändert', 'Das Passwort für deinen 4Creative-Account wurde soeben zurückgesetzt');
header('Location: index.php?page=login');
exit();
@@ -65,8 +86,4 @@
}
displayPage('');
-
- if(!isset($_GET['token']) || !preg_match('/^[a-z0-9A-Z]{32}$/', $_GET['token'])) {
- displayTokenError();
- }
?>
\ No newline at end of file
diff --git a/templates/forgot.html b/templates/forgot.html
index 71489a8..2315f1f 100644
--- a/templates/forgot.html
+++ b/templates/forgot.html
@@ -22,7 +22,7 @@