diff --git a/index.php b/index.php index 3532d639..22ea81fe 100644 --- a/index.php +++ b/index.php @@ -240,6 +240,12 @@ if ($action == 'login') { case 5: $message = $lng['error']['user_banned']; break; + case 6: + $successmessage = $lng['pwdreminder']['changed']; + break; + case 7: + $message = $lng['pwdreminder']['wrongcode']; + break; } $update_in_progress = ''; @@ -265,7 +271,7 @@ if ($action == 'forgotpwd') { Database::pexecute($result_stmt, array("loginname" => $loginname, "email" => $email)); if (Database::num_rows() == 0) { - $result_stmt = Database::prepare("SELECT `adminid`, `name`, `email`, `loginname`, `def_language` FROM `" . TABLE_PANEL_ADMINS . "` + $result_stmt = Database::prepare("SELECT `adminid`, `name`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_ADMINS . "` WHERE `loginname`= :loginname AND `email`= :email" ); @@ -289,35 +295,53 @@ if ($action == 'forgotpwd') { if (($adminchecked && $settings['panel']['allow_preset_admin'] == '1') || $adminchecked == false) { if ($user !== false) { - if ($settings['panel']['password_min_length'] <= 6) { - $password = substr(md5(uniqid(microtime(), 1)), 12, 6); - } else { - // make it two times larger than password_min_length - $rnd = ''; - $minlength = $settings['panel']['password_min_length']; - while (strlen($rnd) < ($minlength * 2)) { - $rnd .= md5(uniqid(microtime(), 1)); - } - $password = substr($rnd, (int)($minlength / 2), $minlength); - } - - $passwordTable = $adminchecked ? TABLE_PANEL_ADMINS : TABLE_PANEL_CUSTOMERS; - $stmt = Database::prepare("UPDATE `" . $passwordTable . "` SET `password`= :password - WHERE `loginname`= :loginname - AND `email`= :email" + // build a activation code + $timestamp = time(); + $first = substr(md5($user['loginname'] . $timestamp . rand(0, $timestamp)), 0, 15); + $third = substr(md5($user['email'] . $timestamp . rand(0, $timestamp)), -15); + $activationcode = $first . $timestamp . $third . substr(md5($third . $timestamp), 0, 10); + + // Drop all existing activation codes for this user + $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "` + WHERE `userid` = :userid + AND `admin` = :admin" ); - Database::pexecute($stmt, array("password" => md5($password), "loginname" => $user['loginname'], "email" => $user['email'])); + $params = array( + "userid" => $adminchecked ? $user['adminid'] : $user['customerid'], + "admin" => $adminchecked ? 1 : 0 + ); + Database::pexecute($stmt, $params); + + // Add new activation code to database + $stmt = Database::prepare("INSERT INTO `" . TABLE_PANEL_ACTIVATION . "` + (userid, admin, creation, activationcode) + VALUES (:userid, :admin, :creation, :activationcode)" + ); + $params = array( + "userid" => $adminchecked ? $user['adminid'] : $user['customerid'], + "admin" => $adminchecked ? 1 : 0, + "creation" => $timestamp, + "activationcode" => $activationcode + ); + Database::pexecute($stmt, $params); $rstlog = FroxlorLogger::getInstanceOf(array('loginname' => 'password_reset'), $settings); - $rstlog->logAction(USR_ACTION, LOG_WARNING, "Password for user '" . $user['loginname'] . "' has been reset!"); - + $rstlog->logAction(USR_ACTION, LOG_WARNING, "User '" . $user['loginname'] . "' requested a link for setting a new password."); + + // Set together our activation link + $protocol = strpos(strtolower($_SERVER['SERVER_PROTOCOL']),'https') === FALSE ? 'http' : 'https'; + $host = $_SERVER['HTTP_HOST']; + $port = $_SERVER['SERVER_PORT'] != 80 ? ':' . $_SERVER['SERVER_PORT'] : ''; + $script = $_SERVER['SCRIPT_NAME']; + $activationlink = $protocol . '://' . $host . $port . $script . '?action=resetpwd&resetcode=' . $activationcode; + $replace_arr = array( 'SALUTATION' => getCorrectUserSalutation($user), 'USERNAME' => $user['loginname'], - 'PASSWORD' => $password + 'LINK' => $activationlink ); - $body = strtr($lng['pwdreminder']['body'], array('%s' => $user['firstname'] . ' ' . $user['name'], '%p' => $password)); + $body = strtr($lng['pwdreminder']['body'], array('%s' => $user['firstname'] . ' ' . $user['name'], '%a' => $activationlink)); $def_language = ($user['def_language'] != '') ? $user['def_language'] : $settings['panel']['standardlanguage']; $result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '` @@ -358,16 +382,16 @@ if ($action == 'forgotpwd') { if ($_mailerror) { $rstlog = FroxlorLogger::getInstanceOf(array('loginname' => 'password_reset'), $settings); $rstlog->logAction(ADM_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg); - redirectTo('index.php', Array('showmessage' => '4', 'customermail' => $user['email']), true); + redirectTo('index.php', array('showmessage' => '4', 'customermail' => $user['email']), true); exit; } $mail->ClearAddresses(); - redirectTo('index.php', Array('showmessage' => '1'), true); + redirectTo('index.php', array('showmessage' => '1'), true); exit; } else { $rstlog = FroxlorLogger::getInstanceOf(array('loginname' => 'password_reset'), $settings); - $rstlog->logAction(USR_ACTION, LOG_WARNING, "User '" . $loginname . "' tried to reset pwd but wasn't found in database!"); + $rstlog->logAction(USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!"); $message = $lng['login']['combination_not_found']; } @@ -391,3 +415,83 @@ if ($action == 'forgotpwd') { eval("echo \"" . getTemplate('fpwd') . "\";"); } + +if ($action == 'resetpwd') { + $message = ''; + + // Remove old activation codes + $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "` + WHERE creation < :oldest" + ); + Database::pexecute($stmt, array("oldest" => time() - 86400)); + + if (isset($_GET['resetcode']) && strlen($_GET['resetcode']) == 50) { + // Check if activation code is valid + $activationcode = $_GET['resetcode']; + $timestamp = substr($activationcode, 15, 10); + $third = substr($activationcode, 25, 15); + $check = substr($activationcode, 40, 10); + + if (substr(md5($third . $timestamp), 0, 10) == $check && $timestamp >= time() - 86400) { + if (isset($_POST['send']) && $_POST['send'] == 'send') { + $stmt = Database::prepare("SELECT `userid`, `admin` FROM `" . TABLE_PANEL_ACTIVATION . "` + WHERE `activationcode` = :activationcode" + ); + $result = Database::pexecute_first($stmt, array("activationcode" => $activationcode)); + + if ($result !== false) { + if ($result['admin'] == 1) { + $new_password = validate($_POST['new_password'], 'new password'); + $new_password_confirm = validate($_POST['new_password_confirm'], 'new password confirm'); + } else { + $new_password = validatePassword($_POST['new_password'], 'new password'); + $new_password_confirm = validatePassword($_POST['new_password_confirm'], 'new password confirm'); + } + + if ($new_password == '') { + $message = $new_password; + } elseif($new_password_confirm == '') { + $message = $new_password_confirm; + } elseif($new_password != $new_password_confirm) { + $message = $new_password . " != " . $new_password_confirm; + } else { + // Update user password + if ($result['admin'] == 1) { + $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_ADMINS . "` + SET `password` = :newpassword + WHERE `adminid` = :userid" + ); + } else { + $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` + SET `password` = :newpassword + WHERE `customerid` = :userid" + ); + } + Database::pexecute($stmt, array("newpassword" => md5($new_password), "userid" => $result['userid'])); + + $rstlog = FroxlorLogger::getInstanceOf(array('loginname' => 'password_reset'), $settings); + $rstlog->logAction(USR_ACTION, LOG_NOTICE, "changed password using password reset."); + + // Remove activation code from DB + $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "` + WHERE `activationcode` = :activationcode + AND `userid` = :userid" + ); + Database::pexecute($stmt, array("activationcode" => $activationcode, "userid" => $result['userid'])); + redirectTo('index.php', array("showmessage" => '6'), true); + } + } else { + redirectTo('index.php', array("showmessage" => '7'), true); + } + } + + eval("echo \"" . getTemplate('rpwd') . "\";"); + + } else { + redirectTo('index.php', array("showmessage" => '7'), true); + } + + } else { + redirectTo('index.php'); + } +} diff --git a/install/froxlor.sql b/install/froxlor.sql index 562c2c0a..98813af5 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -74,6 +74,16 @@ CREATE TABLE `mail_virtual` ( ) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci; +DROP TABLE IF EXISTS `panel_activation`; +CREATE TABLE `panel_activation` ( + `id` int(11) unsigned NOT NULL auto_increment, + `userid` int(11) unsigned NOT NULL default '0', + `admin` tinyint(1) unsigned NOT NULL default '0', + `creation` int(11) unsigned NOT NULL default '0', + `activationcode` varchar(50) default NULL, + PRIMARY KEY (id) +) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci; + DROP TABLE IF EXISTS `panel_admins`; CREATE TABLE `panel_admins` ( @@ -540,7 +550,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'phpconfigs_hidestdsubdomain', '0'), ('panel', 'allow_theme_change_admin', '1'), ('panel', 'allow_theme_change_customer', '1'), - ('panel', 'version', '0.9.31-dev3'); + ('panel', 'version', '0.9.31-dev4'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 7b9545d7..3723b37c 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -2452,3 +2452,23 @@ if (isFroxlorVersion('0.9.31-dev2')) { lastStepStatus(0); updateToVersion('0.9.31-dev3'); } + +if (isFroxlorVersion('0.9.31-dev3')) { + showUpdateStep("Updating from 0.9.31-dev3 to 0.9.31-dev4", true); + lastStepStatus(0); + + showUpdateStep("Adding new panel_activation table"); + Database::query("DROP TABLE IF EXISTS `panel_activation`;"); + $sql = "CREATE TABLE `" . TABLE_PANEL_ACTIVATION . "` ( + id int(11) unsigned NOT NULL AUTO_INCREMENT, + userid int(11) unsigned NOT NULL DEFAULT '0', + admin tinyint(1) unsigned NOT NULL DEFAULT '0', + creation int(11) unsigned NOT NULL DEFAULT '0', + activationcode varchar(50) DEFAULT NULL, + PRIMARY KEY (id) + ) ENGINE=MyISAM;"; + Database::query($sql); + lastStepStatus(0); + + updateToVersion('0.9.31-dev4'); +} diff --git a/install/updates/preconfig/0.9/preconfig_0.9.inc.php b/install/updates/preconfig/0.9/preconfig_0.9.inc.php index 8240a872..af3a8752 100644 --- a/install/updates/preconfig/0.9/preconfig_0.9.inc.php +++ b/install/updates/preconfig/0.9/preconfig_0.9.inc.php @@ -584,4 +584,11 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version) eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";"); } } + + if (versionInUpdate($current_version, '0.9.31-dev4')) { + $has_preconfig = true; + $description = 'The template-variable {PASSWORD} has been replaced with {LINK}. Please update your password reset templates!
'; + $question = ''; + eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";"); + } } diff --git a/lib/tables.inc.php b/lib/tables.inc.php index f5c4aa54..89005dda 100644 --- a/lib/tables.inc.php +++ b/lib/tables.inc.php @@ -23,6 +23,7 @@ define('TABLE_FTP_QUOTALIMITS', 'ftp_quotalimits'); define('TABLE_FTP_QUOTATALLIES', 'ftp_quotatallies'); define('TABLE_MAIL_USERS', 'mail_users'); define('TABLE_MAIL_VIRTUAL', 'mail_virtual'); +define('TABLE_PANEL_ACTIVATION', 'panel_activation'); define('TABLE_PANEL_ADMINS', 'panel_admins'); define('TABLE_PANEL_CUSTOMERS', 'panel_customers'); define('TABLE_PANEL_DATABASES', 'panel_databases'); @@ -71,6 +72,6 @@ define('PACKAGE_LOCKED', 1); define('PACKAGE_ENABLED', 2); // VERSION INFO -$version = '0.9.31-dev3'; +$version = '0.9.31-dev4'; $dbversion = '2'; $branding = ''; diff --git a/lng/english.lng.php b/lng/english.lng.php index badfc524..02308910 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -107,7 +107,7 @@ $lng['index']['accountdetails'] = 'Account details'; $lng['changepassword']['old_password'] = 'Old password'; $lng['changepassword']['new_password'] = 'New password'; -$lng['changepassword']['new_password_confirm'] = 'New password (confirm)'; +$lng['changepassword']['new_password_confirm'] = 'Confirm password'; $lng['changepassword']['new_password_ifnotempty'] = 'New password (empty = no change)'; $lng['changepassword']['also_change_ftp'] = ' also change password of the main FTP account'; @@ -851,8 +851,8 @@ $lng['login']['email'] = 'E-mail address'; $lng['login']['remind'] = 'Reset my password'; $lng['login']['usernotfound'] = 'User not found!'; $lng['pwdreminder']['subject'] = 'Froxlor - Password reset'; -$lng['pwdreminder']['body'] = 'Hello %s,\n\nyour froxlor password has been reset!\nThe new password is: %p\n\nThank you,\nyour administrator'; -$lng['pwdreminder']['success'] = 'Password reset successfully.
You now should receive an email with your new password.'; +$lng['pwdreminder']['body'] = 'Hello %s,\n\nhere is your link for setting a new password. This link is valid for the next 24 hours.\n\n%a\n\nThank you,\nyour administrator'; +$lng['pwdreminder']['success'] = 'Password reset successfully requested. Please follow the instructions in the email you received.'; // ADDED IN 1.2.19-svn18 @@ -1983,3 +1983,7 @@ $lng['error']['send_report_title'] = 'Send error report'; $lng['error']['send_report_desc'] = 'Thank you for reporting this error and helping us to froxlor improve froxlor.
This is the email which will be sent to the froxlor developer team:'; $lng['error']['send_report'] = 'Send report'; $lng['error']['notallowedtouseaccounts'] = 'Your account does not allow using IMAP/POP3. You cannot add email accounts.'; +$lng['pwdreminder']['changed'] = 'Your password has been successfully changed. You can now login using this password.'; +$lng['pwdreminder']['wrongcode'] = 'Sorry, the used activationcode does not exist or is already expired.'; +$lng['admin']['templates']['LINK'] = 'Replaced with the customers password reset link.'; +$lng['pwdreminder']['choosenew'] = 'Choose new password'; diff --git a/lng/german.lng.php b/lng/german.lng.php index a8a85d8e..7dab486f 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -107,7 +107,7 @@ $lng['index']['accountdetails'] = 'Kontodaten'; $lng['changepassword']['old_password'] = 'Altes Passwort'; $lng['changepassword']['new_password'] = 'Neues Passwort'; -$lng['changepassword']['new_password_confirm'] = 'Neues Passwort (bestätigen)'; +$lng['changepassword']['new_password_confirm'] = 'Passwortbestätigung'; $lng['changepassword']['new_password_ifnotempty'] = 'Neues Passwort (leer = nicht ändern)'; $lng['changepassword']['also_change_ftp'] = 'Auch Passwort vom Haupt-FTP-Zugang ändern'; @@ -850,8 +850,8 @@ $lng['login']['email'] = 'E-Mail Adresse'; $lng['login']['remind'] = 'Passwort zurücksetzen'; $lng['login']['usernotfound'] = 'Fehler: Unbekannter Benutzer!'; $lng['pwdreminder']['subject'] = 'Froxlor - Passwort zurückgesetzt'; -$lng['pwdreminder']['body'] = 'Hallo "%s",\n\nIhr Froxlor Passwort wurde zurückgesetzt!\nDas neue Passwort lautet: %p\n\nVielen Dank,\nIhr Administrator'; -$lng['pwdreminder']['success'] = 'Passwort erfolgreich zurückgesetzt.
Sie sollten nun eine E-Mail mit dem neuen Passwort erhalten.'; +$lng['pwdreminder']['body'] = 'Hallo "%s",\n\nHiermit erhalten Sie den Link um ein neues Passwort zu setzen. Dieser Link ist für die nächsten 24 Stunden gültig.\n\n%a\n\nVielen Dank,\nIhr Administrator'; +$lng['pwdreminder']['success'] = 'Das Zurücksetzen des Passworts wurde erfolgreich angefordert. Sie sollten nun eine E-Mail mit weiteren Anweisungen erhalten.'; // ADDED IN 1.2.19-svn18 @@ -1709,3 +1709,7 @@ $lng['error']['send_report_title'] = 'Fehler melden'; $lng['error']['send_report_desc'] = 'Danke, dass Sie uns diesen Fehler melden und damit helfen Froxlor zu verbessern.
Folgender Bericht wird per Mail an das Froxlor Entwickler Team gesendet.'; $lng['error']['send_report'] = 'Fehlerbericht senden'; $lng['error']['notallowedtouseaccounts'] = 'Ihrem Konto ist die Nutzung von IMAP/POP3 nicht erlaubt, daher können keine E-Mail Konten angelegt werden'; +$lng['pwdreminder']['changed'] = 'Ihr Passwort wurde erfolgreich geändert. Sie können sich nun damit '; +$lng['pwdreminder']['wrongcode'] = 'Der verwendete Aktivierungscode ist entweder nicht gültig oder bereits abgelaufen.'; +$lng['admin']['templates']['LINK'] = 'Wird mit dem Link zum Zurücksetzen des Passworts ersetzt.'; +$lng['pwdreminder']['choosenew'] = 'Neues Passwort auswählen'; diff --git a/templates/Froxlor/admin/templates/templates_add_2.tpl b/templates/Froxlor/admin/templates/templates_add_2.tpl index 2fa2ce77..ab4863a9 100644 --- a/templates/Froxlor/admin/templates/templates_add_2.tpl +++ b/templates/Froxlor/admin/templates/templates_add_2.tpl @@ -115,8 +115,8 @@ $header {$lng['admin']['templates']['USERNAME']} - {PASSWORD} - {$lng['admin']['templates']['PASSWORD']} + {LINK} + {$lng['admin']['templates']['LINK']} diff --git a/templates/Froxlor/login/rpwd.tpl b/templates/Froxlor/login/rpwd.tpl new file mode 100644 index 00000000..3d25daf4 --- /dev/null +++ b/templates/Froxlor/login/rpwd.tpl @@ -0,0 +1,37 @@ +$header +
+
+ Froxlor Server Management Panel +
+ +
+
{$lng['error']['error']}
+
$message
+
+
+
+

{$lng['pwdreminder']['choosenew']}

+
+
+ Froxlor - {$lng['login']['presend']} +

+   + +

+

+   + +

+

+ + + +

+
+
+ +
+
+$footer diff --git a/templates/Sparkle/admin/templates/templates_add_2.tpl b/templates/Sparkle/admin/templates/templates_add_2.tpl index 8478416c..27030e9b 100644 --- a/templates/Sparkle/admin/templates/templates_add_2.tpl +++ b/templates/Sparkle/admin/templates/templates_add_2.tpl @@ -114,8 +114,8 @@ $header {$lng['admin']['templates']['USERNAME']} - {PASSWORD} - {$lng['admin']['templates']['PASSWORD']} + {LINK} + {$lng['admin']['templates']['LINK']} diff --git a/templates/Sparkle/login/rpwd.tpl b/templates/Sparkle/login/rpwd.tpl new file mode 100644 index 00000000..3d25daf4 --- /dev/null +++ b/templates/Sparkle/login/rpwd.tpl @@ -0,0 +1,37 @@ +$header +
+
+ Froxlor Server Management Panel +
+ +
+
{$lng['error']['error']}
+
$message
+
+
+
+

{$lng['pwdreminder']['choosenew']}

+
+
+ Froxlor - {$lng['login']['presend']} +

+   + +

+

+   + +

+

+ + + +

+
+
+ +
+
+$footer