Squirrel Mail - Change Password Plugin - Wicked Simple Version

It's a long sad story as to why I set up an email server. Mostly long. Arguably not sad, since it is collecting email.

However, lacking the usual accessories provided by a hosting company and having issued a collection of awful (secure) passwords, it was abundantly clear a password reset mechanism would be required.

This isn't really suitable for password recovery, because it relies on the person being able to log into Squirrel Mail to change their password. If they have already forgotten it - they're toast.

Thus - one must encourage the users to set the password to something they have a chance at typing correctly and maybe remembering.

Please note I'm not implying the users are incapable of handling a password. I issued passwords which would be difficult to type and virtually impossible to remember.

Here's the code ...

define('SM_PATH', '../../');
include_once(SM_PATH . 'include/validate.php');

// Make sure plugin is activated!
//
global $plugins;
if (!in_array('change_password', $plugins))
   exit;


global $color;
displayPageHeader($color, 'None');

sqgetGlobalVar('username',   $username,     SQ_SESSION);

define('MIN_PASSWORD',10);

$error = $message = null;
$dbConn = pg_connect('dbname=mail user=somebody password=supersecret');
if ($dbConn !== false) {
	if (!empty($_POST['current-password'])) {
		$currentPassword = preg_replace('/[^a-z0-9\_\@\#\$\%\^\&\*\(\)\+\?\>\<\;\:]/i','',$_POST['current-password']);
		$query = 'SELECT password FROM users WHERE userid = $1';
		$result = pg_query_params($query,[$username]);
		if (pg_affected_rows($result) === 1) {
			$row = pg_fetch_assoc($result);
			$passwordPieces = explode('$',$row['password']);
			$encryptedCheck = '{SHA512-CRYPT}' . crypt($currentPassword, '$6$'.$passwordPieces[2].'$');
			if ($encryptedCheck !== $row['password']) {
				$error = 'Current password mismatch';
			}
		} else {
			$error = 'Current user mismatch';
		}
	}
	
	if ($error === null && isset($_POST['new-password'],$_POST['confirm-password'])) {
		$newPassword = trim($_POST['new-password']);
		$confirmPassword = trim($_POST['confirm-password']);
		if (strlen($newPassword) < MIN_PASSWORD) {
			$error = 'Password must be at least '.MIN_PASSWORD.' characters';
		} else {
			if ($newPassword !== $confirmPassword) {
				$error = 'Passwords must match';
			} else {
				$checkForUppercase = preg_match('/[A-Z]/',$newPassword);
				$checkForLowercase = preg_match('/[a-z]/',$newPassword);
				$checkForDigit = preg_match('/\d/',$newPassword);
				$checkForSymbol = preg_match('/[\_\!\@\#\$\%\^\&\*\(\)\+\?\>\<\;\:]/',$newPassword);
				if ($checkForUppercase && $checkForLowercase && $checkForDigit && $checkForSymbol) {
					$random = str_shuffle(md5(rand(-1000,1000)));
                                        $encrypted = '{SHA512-CRYPT}' . crypt($newPassword, '$6$'.$random.'$');
					$query = 'UPDATE users SET password = $1 WHERE userid = $2';
					$result = pg_query_params($query,[$encrypted,$username]);
					if (pg_affected_rows($result) === 1) {
						$message = 'Success';
					} else {
						$error = 'Unable to update the password';
					}
				} else {
					$error = 'Password must contain at least one uppercase letter, one lowercase letter, one digit, and one symbol';
				}
			}
		}
	}
	pg_close();
} else {
	$error = 'Unable to update the password';
}

?>
<?php if ($error !== null) : ?>

<?= $error ?>

<?php endif ?> <?php if ($message !== null) : ?>

<?= $message ?>

<?php endif ?>







The rest of the files to make the plugin work and the internationalization are left to you dear reader. This is just the stuff you need to make it work.

Enjoy.

The blog code formatter modified my HTML. That's okay - what I'm really sharing is the PHP.