mirror of
https://github.com/postfixadmin/postfixadmin.git
synced 2024-09-19 19:22:14 +02:00
Adding support for password expiration. Please read README.password_expiration for more details
This commit is contained in:
parent
c3d3898eb2
commit
e786609aa9
38
README.password_expiration
Normal file
38
README.password_expiration
Normal file
@ -0,0 +1,38 @@
|
||||
*Description
|
||||
This extension adds support for password expiration.
|
||||
It is designed to have expiration on users passwords. An email is sent when the password is expiring in 30 days, then 14 days, then 7 days.
|
||||
It is strongly inspired by https://abridge2devnull.com/posts/2014/09/29/dovecot-user-password-expiration-notifications-updated-4122015/, and adapted to fit with Postfix Admin & Roundcube's password plugin
|
||||
|
||||
*Installation
|
||||
Perform the following changes:
|
||||
|
||||
**Changes in MySQL/MariaDB mailbox table (as defined in $CONF['database_tables'] from config.inc.php):
|
||||
You are invited to backup your DB first, and ensure the table name is correct.
|
||||
|
||||
Execute the attached SQL script (password_expiration.sql) that will add the required columns. The expiration value for existing users will be set to 90 days. If you want a different value, edit the last line in the script and replace 90 by the required value.
|
||||
|
||||
**Changes in Postfix Admin :
|
||||
To enable password expiration, add the following to your config.inc.php file:
|
||||
$CONF['password_expiration_enabled'] = 'YES';
|
||||
|
||||
Do not forget to set the expiration value (in days)
|
||||
$CONF['password_expiration_value'] = '90';
|
||||
|
||||
All my tests are performed using $CONF['encrypt'] = 'md5crypt';
|
||||
|
||||
**If you are using Roundcube's password plugin, you should also adapt the $config['password_query'] value.
|
||||
I recommend to use:
|
||||
$config['password_query'] = 'UPDATE mailbox SET password=%c, modified=now(),pw_expires_on=now() + interval 90 day, thirty=0,fourteen=0,seven=0 where username=%u';
|
||||
of cource you may adapt to the expected expiration value
|
||||
|
||||
All my tests are performed using $config['password_algorithm'] = 'md5-crypt';
|
||||
|
||||
**Changes in Dovecot (adapt if you use another LDA)
|
||||
Edit dovecot-mysql.conf file, and replace the user_query (and only this one) by this query:
|
||||
user_query = SELECT concat('/var/vmail/', maildir) as home, concat('maildir:/var/vmail/', maildir) as mail, 20001 AS uid, 20001 AS gid, concat('dirsize:storage=', quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1' AND pw_expires_on > now()
|
||||
if course you may require to adapt the uid, gid, maildir and table to your setup
|
||||
|
||||
**Changes in system
|
||||
You need to have a script running on a daily basis to check password expiration and send emails 30, 14 and 7 days before password expiration (script attached: check_mailpass_expiration.sh).
|
||||
Edit the script to adapt the variables to your setup.
|
||||
Ensure the user running check_mailpass_expiration.sh is allowed to access (read-write) your database.
|
34
check_mailpass_expiration.sh
Normal file
34
check_mailpass_expiration.sh
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
#Adapt to your setup
|
||||
|
||||
POSTFIX_DB="postfix_test"
|
||||
POSTFIX_USER="postfixadmin"
|
||||
POSTFIX_PASSWORD="my_password_is_strong"
|
||||
|
||||
#All the rest should be OK
|
||||
QUERY30DAYS="SELECT username,pw_expires_on FROM mailbox WHERE pw_expires_on > now() + interval 29 DAY AND pw_expires_on < now() + interval 30 day AND thirty = false;"
|
||||
QUERY14DAYS="SELECT username,pw_expires_on FROM mailbox WHERE pw_expires_on > now() + interval 13 DAY AND pw_expires_on < now() + interval 14 day AND fourteen = false;"
|
||||
QUERY7DAYS="SELECT username,pw_expires_on FROM mailbox WHERE pw_expires_on > now() + interval 6 DAY AND pw_expires_on < now() + interval 7 day AND seven = false;"
|
||||
|
||||
function notifyThirtyDays() {
|
||||
mysql -B -u "$POSTFIX_USER" -p"$POSTFIX_PASSWORD" "$POSTFIX_DB" -e "$QUERY30DAYS" | while read -a RESULT; do
|
||||
echo -e "Dear User, \n Your password will expire on ${RESULT[1]}" | mail -s "Password 30 days before expiration notication" -r noreply@eyetech.fr ${RESULT[0]}
|
||||
echo "UPDATE mailbox SET thirty = true WHERE username = '${RESULT[0]}';" | mysql -u postfix postfix_test;done
|
||||
}
|
||||
|
||||
function notifyFourteenDays() {
|
||||
mysql -B -u "$POSTFIX_USER" -p"$POSTFIX_PASSWORD" "$POSTFIX_DB" -e "$QUERY14DAYS" | while read -a RESULT; do
|
||||
echo -e "Dear User, \n Your password will expire on ${RESULT[1]}" | mail -s "Password 14 days before expiration notication" -r noreply@eyetech.fr ${RESULT[0]}
|
||||
echo "UPDATE mailbox SET fourteen = true WHERE username = '${RESULT[0]}';" | mysql -u postfix postfix_test;done
|
||||
}
|
||||
|
||||
function notifySevenDays() {
|
||||
mysql -B -u "$POSTFIX_USER" -p"$POSTFIX_PASSWORD" "$POSTFIX_DB" -e "$QUERY7DAYS" | while read -a RESULT; do
|
||||
echo -e "Dear User, \n Your password will expire on ${RESULT[1]}" | mail -s "Password 7 days before expiraiton notication" -r noreply@eyetech.fr ${RESULT[0]}
|
||||
echo "UPDATE mailbox SET seven = true WHERE username = '${RESULT[0]}';" | mysql -u postfix postfix_test;done
|
||||
}
|
||||
|
||||
notifyThirtyDays # Execute the function for 30 day notices
|
||||
notifyFourteenDays # Execute the function for 14 day notices
|
||||
notifySevenDays # Execute the function for 7 day notices
|
||||
|
@ -661,6 +661,12 @@ $CONF['theme_custom_css'] = '';
|
||||
// change to boolean true to enable xmlrpc
|
||||
$CONF['xmlrpc_enabled'] = false;
|
||||
|
||||
//Account expiration info
|
||||
//If you want to display the password expiracy status of the accounts (read-only)
|
||||
//More details in README.password_expiration
|
||||
$CONF['password_expiration_enable'] = 'YES';
|
||||
$CONF['password_expiration_value'] = '90';
|
||||
|
||||
// If you want to keep most settings at default values and/or want to ensure
|
||||
// that future updates work without problems, you can use a separate config
|
||||
// file (config.local.php) instead of editing this file and override some
|
||||
|
@ -1865,7 +1865,7 @@ function db_delete($table, $where, $delete, $additionalwhere='') {
|
||||
* @param array (optional) - array of fields to set to now() - default: array('created', 'modified')
|
||||
* @return int - number of inserted rows
|
||||
*/
|
||||
function db_insert($table, $values, $timestamp = array('created', 'modified')) {
|
||||
function db_insert ($table, $values, $timestamp = array('created', 'modified'), $timestamp_expiration = array('pw_expires_on') ) {
|
||||
$table = table_by_key($table);
|
||||
|
||||
foreach (array_keys($values) as $key) {
|
||||
@ -1879,6 +1879,18 @@ function db_insert($table, $values, $timestamp = array('created', 'modified')) {
|
||||
$values[$key] = "now()";
|
||||
}
|
||||
}
|
||||
if ($table == 'mailbox') {
|
||||
global $CONF;
|
||||
if ($CONF['password_expiration_enabled'] == 'YES') {
|
||||
$expires_warning_values = array('thirty', 'fourteen', 'seven');
|
||||
foreach($expires_warning_values as $key) {
|
||||
$values[$key] = escape_string($key) . "=0";
|
||||
}
|
||||
foreach($timestamp_expiration as $key) {
|
||||
$values[$key] = "now() + interval " . $CONF['password_expiration_value'] . " day";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sql_values = "(" . implode(",", escape_string(array_keys($values))).") VALUES (".implode(",", $values).")";
|
||||
|
||||
@ -1927,6 +1939,17 @@ function db_update_q($table, $where, $values, $timestamp = array('modified')) {
|
||||
$sql_values[$key] = escape_string($key) . "=now()";
|
||||
}
|
||||
}
|
||||
if ($table == 'mailbox') {
|
||||
global $CONF;
|
||||
if ($CONF['password_expiration_enabled'] == 'YES') {
|
||||
$key = 'pw_expires_on';
|
||||
$sql_values[$key] = escape_string($key) . "=now() + interval " . $CONF['password_expiration_value'] . " day";
|
||||
$expires_warning_values = array('thirty', 'fourteen', 'seven');
|
||||
foreach($expires_warning_values as $key) {
|
||||
$sql_values[$key] = escape_string($key) . "=0";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sql="UPDATE $table SET " . implode(",", $sql_values) . " WHERE $where";
|
||||
|
||||
|
@ -407,6 +407,7 @@ $PALANG['pFetchmail_desc_returned_text'] = 'Text message from last polling';
|
||||
|
||||
$PALANG['dateformat_pgsql'] = 'YYYY-mm-dd'; # translators: rearrange to your local date format, but make sure it's a valid PostgreSQL date format
|
||||
$PALANG['dateformat_mysql'] = '%Y-%m-%d'; # translators: rearrange to your local date format, but make sure it's a valid MySQL date format
|
||||
$PALANG['password_expiration'] = 'Pass expires';
|
||||
|
||||
$PALANG['please_keep_this_as_last_entry'] = ''; # needed for language-check.sh
|
||||
/* vim: set expandtab ft=php softtabstop=3 tabstop=3 shiftwidth=3: */
|
||||
|
@ -398,6 +398,7 @@ $PALANG['pFetchmail_desc_date'] = 'Date de la dernière vérification/changement
|
||||
$PALANG['pFetchmail_desc_returned_text'] = 'Message de la dernière vérification';
|
||||
$PALANG['dateformat_pgsql'] = 'dd-mm-YYYY';
|
||||
$PALANG['dateformat_mysql'] = '%d-%m-%Y';
|
||||
$PALANG['password_expiration'] = 'Expiration du mot de passe';
|
||||
|
||||
$PALANG['please_keep_this_as_last_entry'] = ''; # needed for language-check.sh
|
||||
/* vim: set expandtab ft=php softtabstop=3 tabstop=3 shiftwidth=3: */
|
||||
|
@ -49,6 +49,7 @@ class MailboxHandler extends PFAHandler {
|
||||
'token_validity' => pacol(1, 0, 0, 'ts', '' , '', date("Y-m-d H:i:s",time())),
|
||||
'created' => pacol(0, 0, 1, 'ts', 'created' , '' ),
|
||||
'modified' => pacol(0, 0, 1, 'ts', 'last_modified' , '' ),
|
||||
'pw_expires_on' => pacol( 0, 0, 1, 'ts', 'password_expiration' , '' ),
|
||||
# TODO: add virtual 'notified' column and allow to display who received a vacation response?
|
||||
);
|
||||
|
||||
|
5
password_expiration.sql
Normal file
5
password_expiration.sql
Normal file
@ -0,0 +1,5 @@
|
||||
ALTER TABLE mailbox ADD COLUMN pw_expires_on TIMESTAMP DEFAULT now() not null;
|
||||
ALTER TABLE mailbox ADD COLUMN thirty boolean not null DEFAULT false;
|
||||
ALTER TABLE mailbox ADD COLUMN fourteen boolean not null DEFAULT false;
|
||||
ALTER TABLE mailbox ADD COLUMN seven boolean not null DEFAULT false;
|
||||
UPDATE mailbox set pw_expires_on = now() + interval 90 day;
|
@ -165,6 +165,7 @@ $tAlias = $handler->result();
|
||||
#
|
||||
|
||||
$display_mailbox_aliases = Config::bool('alias_control_admin');
|
||||
$password_expiration = Config::bool('password_expiration');
|
||||
|
||||
# build the sql query
|
||||
$sql_select = "SELECT $table_mailbox.* ";
|
||||
@ -190,6 +191,10 @@ if ($display_mailbox_aliases) {
|
||||
$sql_join .= " LEFT JOIN $table_alias ON $table_mailbox.username=$table_alias.address ";
|
||||
}
|
||||
|
||||
if ($password_expiration) {
|
||||
$sql_select .= ", $table_mailbox.pw_expires_on as password_expiration ";
|
||||
}
|
||||
|
||||
if (Config::bool('vacation_control_admin')) {
|
||||
$table_vacation = table_by_key('vacation');
|
||||
$sql_select .= ", $table_vacation.active AS v_active ";
|
||||
|
@ -13,6 +13,9 @@
|
||||
<td>{$PALANG.name}</td>
|
||||
{if $CONF.quota===YES}<td>{$PALANG.pOverview_mailbox_quota}</td>{/if}
|
||||
<td>{$PALANG.last_modified}</td>
|
||||
{if $CONF.password_expiration===YES}
|
||||
<td>{$PALANG.password_expiration}</td>
|
||||
{/if}
|
||||
<td>{$PALANG.active}</td>
|
||||
{assign var="colspan" value="`$colspan-6`"}
|
||||
<td colspan="{$colspan}"> </td>
|
||||
@ -74,6 +77,9 @@
|
||||
</td>
|
||||
{/if}
|
||||
<td>{$item.modified}</td>
|
||||
{if $CONF.password_expiration===YES}
|
||||
<td>{$item.password_expiration}</td>
|
||||
{/if}
|
||||
<td><a href="{#url_editactive#}mailbox&id={$item.username|escape:"url"}&active={if ($item.active==0)}1{else}0{/if}&token={$smarty.session.PFA_token|escape:"url"}"
|
||||
>{if $item.active==1}{$PALANG.YES}{else}{$PALANG.NO}{/if}</a></td>
|
||||
{if $CONF.vacation_control_admin===YES && $CONF.vacation===YES}
|
||||
|
Loading…
Reference in New Issue
Block a user