diff --git a/admin/inc/class.boaccounts.inc.php b/admin/inc/class.boaccounts.inc.php
index dd88bdb4ad..8c574be762 100755
--- a/admin/inc/class.boaccounts.inc.php
+++ b/admin/inc/class.boaccounts.inc.php
@@ -260,7 +260,7 @@
{
return False;
}
-
+ //error_log(array2string($userData));
$accountPrefix = '';
if(isset($GLOBALS['egw_info']['server']['account_prefix']))
{
@@ -441,6 +441,7 @@
/* stores the userdata */
function save_user($_userData)
{
+ //error_log(__METHOD__.array2string($_userData));
$account =& CreateObject('phpgwapi.accounts',$_userData['account_id'],'u');
$account->update_data($_userData);
$account->save_repository();
@@ -458,6 +459,13 @@
$GLOBALS['egw']->hooks->process($GLOBALS['hook_values']+array(
'location' => 'changepassword'
),False,True); // called for every app now, not only enabled ones)
+ if ($_userData['account_lastpwd_change']==0)
+ {
+ // change password sets the shadow_timestamp/account_lastpwd_change timestamp
+ // so we need to reset that to 0 as Admin required the change of password upon next login
+ unset($_userData['account_passwd']);
+ $this->save_user($_userData);
+ }
}
$apps =& CreateObject('phpgwapi.applications',(int)$_userData['account_id']);
diff --git a/admin/inc/class.uiaccounts.inc.php b/admin/inc/class.uiaccounts.inc.php
index 8e569db5c4..c5a633c2cb 100755
--- a/admin/inc/class.uiaccounts.inc.php
+++ b/admin/inc/class.uiaccounts.inc.php
@@ -573,6 +573,7 @@
'account_groups' => $_POST['account_groups'],
'anonymous' => $_POST['anonymous'],
'changepassword' => $_POST['changepassword'],
+ 'mustchangepassword' => $_POST['mustchangepassword'],
'account_permissions' => $_POST['account_permissions'],
'homedirectory' => $_POST['homedirectory'],
'loginshell' => $_POST['loginshell'],
@@ -580,7 +581,7 @@
'account_email' => $email
/* 'file_space' => $_POST['account_file_space_number'] . "-" . $_POST['account_file_space_type'] */
);
-
+ if ($userData['mustchangpassword']) $userData['account_lastpwd_change']=0;
/* when does the account expire */
if ($_POST['expires'] !== '' && !$_POST['never_expires'])
{
@@ -863,6 +864,7 @@
'account_primary_group' => $_POST['account_primary_group'],
'anonymous' => $_POST['anonymous'],
'changepassword' => $_POST['changepassword'],
+ 'mustchangepassword' => $_POST['mustchangepassword'],
'account_permissions' => $_POST['account_permissions'],
'homedirectory' => $_POST['homedirectory'],
'loginshell' => $_POST['loginshell'],
@@ -870,6 +872,21 @@
'account_email' => $email,
/* 'file_space' => $_POST['account_file_space_number'] . "-" . $_POST['account_file_space_type'] */
);
+ if ($userData['mustchangepassword'])
+ {
+ $userData['account_lastpwd_change']=0;
+ }
+ else
+ {
+ $accountid = $account_id;
+ settype($account_id,'integer');
+ $account_id = (int)($_GET['account_id'] ? $_GET['account_id'] : $accountid);
+
+ //echo $account_id.'#
';
+ $prevVal = $GLOBALS['egw']->accounts->id2name($account_id,'account_lastpwd_change').'#
';
+ //echo $prevVal.'#
'; // previous Value was force password change by admin
+ if ($prevVal==0) $userData['account_lastpwd_change']=egw_time::to('now','ts');
+ }
if($userData['account_primary_group'] && (!isset($userData['account_groups']) || !in_array($userData['account_primary_group'],$userData['account_groups'])))
{
$userData['account_groups'][] = (int)$userData['account_primary_group'];
@@ -965,6 +982,7 @@
'lang_groups' => lang('Groups'),
'lang_anonymous' => lang('Anonymous user (not shown in list sessions)'),
'lang_changepassword'=> lang('Can change password'),
+ 'lang_mustchangepassword'=> lang('Must change password upon next login'),
'lang_firstname' => lang('First Name'),
'lang_lastlogin' => lang('Last login'),
'lang_lastloginfrom' => lang('Last login from'),
@@ -985,6 +1003,7 @@
$acl =& CreateObject('phpgwapi.acl',(int)$_GET['account_id']);
$var['anonymous'] = $acl->check('anonymous',1,'phpgwapi') ? ' X' : ' ';
$var['changepassword'] = !$acl->check('nopasswordchange',1,'preferences') ? ' X' : ' ';
+ $var['mustchangepassword']= $userData['account_lastpwd_change']==0 ? ' X' : ' ';
unset($acl);
if ($userData['status'])
@@ -1286,6 +1305,7 @@
function create_edit_user($_account_id,$_userData='',$_errors='')
{
+ //_debug_array($_userData);
$GLOBALS['egw_info']['flags']['include_xajax'] = true;
$jscal =& CreateObject('phpgwapi.jscalendar');
@@ -1341,6 +1361,7 @@
$acl->read_repository();
$userData['anonymous'] = $acl->check('anonymous',1,'phpgwapi');
$userData['changepassword'] = !$acl->check('nopasswordchange',1,'preferences');
+ $userData['mustchangepassword'] = ($userData['account_lastpwd_change']==0?true:false);
unset($acl);
}
else
@@ -1351,6 +1372,7 @@
$userGroups = Array();
$userData['anonymous'] = False;
$userData['changepassword'] = True;
+ $userData['mustchangepassword'] = false;
}
$allGroups = $account->get_list('groups');
}
@@ -1380,6 +1402,7 @@
'lang_firstname' => lang('First Name'),
'lang_anonymous' => lang('Anonymous User (not shown in list sessions)'),
'lang_changepassword' => lang('Can change password'),
+ 'lang_mustchangepassword'=> lang('Must change password upon next login'),
'lang_button' => ($_account_id?lang('Save'):lang('Add')),
'lang_passwds_unequal' => lang('The two passwords are not the same'),
/* 'lang_file_space' => lang('File Space') */
@@ -1449,6 +1472,7 @@
'loginshell' => $loginshell,
'anonymous' => '',
'changepassword' => '',
+ 'mustchangepassword' => '',
'account_status' => '',
'account_firstname' => '',
'account_lastname' => '',
diff --git a/admin/templates/default/account_form.tpl b/admin/templates/default/account_form.tpl
index 378e706f17..771b5d3191 100644
--- a/admin/templates/default/account_form.tpl
+++ b/admin/templates/default/account_form.tpl
@@ -61,6 +61,13 @@ function check_password(id)
{password_fields}
+
+
+ {lang_mustchangepassword} |
+ {mustchangepassword} |
+ |
+ |
+
{lang_changepassword} |
diff --git a/admin/templates/default/config.tpl b/admin/templates/default/config.tpl
index 71ba843d79..12f3a2fb71 100644
--- a/admin/templates/default/config.tpl
+++ b/admin/templates/default/config.tpl
@@ -231,6 +231,20 @@
+
+ {lang_Force_users_to_change_their_password_regularily?(empty_for_no,number_for_after_that_number_of_days}: |
+
+
+ |
+
+
+
+ {lang_Force_password_strength_(1-5,_default_empty: no check against rules for a strong password)?}: |
+
+
+ |
+
+
{lang_Admin_email_addresses_(comma-separated)_to_be_notified_about_the_blocking_(empty_for_no_notify)}: |
diff --git a/home/index.php b/home/index.php
index 2759e9f6da..4b32c1e41e 100755
--- a/home/index.php
+++ b/home/index.php
@@ -19,8 +19,8 @@
*/
$GLOBALS['egw_info'] = array(
'flags' => array(
- 'noheader' => False,
- 'nonavbar' => False,
+ 'noheader' => true,//False,
+ 'nonavbar' => true,//False,
'currentapp' => 'home',
'enable_network_class' => False,
'enable_contacts_class' => False,
@@ -30,7 +30,9 @@
);
include('../header.inc.php');
-
+ auth::check_password_age('home','index');
+ $GLOBALS['egw_info']['flags']['nonavbar']=false;
+ common::egw_header();
/*
** Initializing the template
*/
@@ -288,4 +290,3 @@
//$GLOBALS['egw']->common->debug_phpgw_info();
//$GLOBALS['egw']->common->debug_list_core_functions();
$GLOBALS['egw']->common->egw_footer();
-?>
diff --git a/infolog/index.php b/infolog/index.php
index e10420d3e6..059ad184f1 100644
--- a/infolog/index.php
+++ b/infolog/index.php
@@ -18,7 +18,7 @@ $GLOBALS['egw_info'] = array(
)
);
include('../header.inc.php');
-
+auth::check_password_age('infolog','index');
include_once(EGW_INCLUDE_ROOT.'/infolog/setup/setup.inc.php');
if ($setup_info['infolog']['version'] != $GLOBALS['egw_info']['apps']['infolog']['version'])
{
diff --git a/phpgwapi/inc/class.accounts_ldap.inc.php b/phpgwapi/inc/class.accounts_ldap.inc.php
index 08fed7c1f0..779ae664e9 100644
--- a/phpgwapi/inc/class.accounts_ldap.inc.php
+++ b/phpgwapi/inc/class.accounts_ldap.inc.php
@@ -504,7 +504,7 @@ class accounts_ldap
// shadowexpire is in days since 1970/01/01 (equivalent to a timestamp (int UTC!) / (24*60*60)
'account_status' => isset($data['shadowexpire']) && $data['shadowexpire'][0]*24*3600+$utc_diff < time() ? false : 'A',
'account_expires' => isset($data['shadowexpire']) && $data['shadowexpire'][0] ? $data['shadowexpire'][0]*24*3600+$utc_diff : -1, // LDAP date is in UTC
- 'account_lastpasswd_change' => isset($data['shadowlastchange']) ? $data['shadowlastchange'][0]*24*3600+$utc_diff : null,
+ 'account_lastpwd_change' => isset($data['shadowlastchange']) ? $data['shadowlastchange'][0]*24*3600+$utc_diff : null,
// lastlogin and lastlogin from are not availible via the shadowAccount object class
// 'account_lastlogin' => $data['phpgwaccountlastlogin'][0],
// 'account_lastloginfrom' => $data['phpgwaccountlastloginfrom'][0],
@@ -591,7 +591,7 @@ class accounts_ldap
unset($to_write['shadowexpire']); // gives protocoll error otherwise
}
- if ($data['account_lastpasswd_change']) $to_write['shadowlastchange'] = $data['lastpasswd_change']/(24*3600);
+ if ($data['account_lastpwd_change']) $to_write['shadowlastchange'] = $data['lastpwd_change']/(24*3600);
// lastlogin and lastlogin from are not availible via the shadowAccount object class
// $to_write['phpgwaccountlastlogin'] = $data['lastlogin'];
diff --git a/phpgwapi/inc/class.auth.inc.php b/phpgwapi/inc/class.auth.inc.php
index 462bb3a4ab..39cab5d3f4 100644
--- a/phpgwapi/inc/class.auth.inc.php
+++ b/phpgwapi/inc/class.auth.inc.php
@@ -55,6 +55,46 @@ class auth
}
}
+ /**
+ * check_password_age
+ * check if users are supposed to change their password every x sdays, then check if password is of old age
+ * or the devil-admin reset the users password and forced the user to change his password on next login.
+ *
+ * @param string $app to know where you are/ or where you want to go
+ * @param string $class to know where you are/ or where you want to go
+ * @param string $method to know where you are/ or where you want to go
+ * @return boolean true if check determined, that you passed the test, otherwise void, as we get redirected
+ */
+ static function check_password_age($app='', $class='', $method='')
+ {
+ //echo egw_time::to('now','ts').' ';
+ //echo $GLOBALS['egw_info']['user']['account_lastpwd_change'].' ';
+ //echo ($GLOBALS['egw_info']['server']['change_pwd_every_x_days']*86400).' ';
+ //echo egw_time::to('now','ts')-($GLOBALS['egw_info']['server']['change_pwd_every_x_days']*86400).' ';
+ if (!($app == 'preferences' && $class == 'uipassword' && $method=='change') &&
+ (($GLOBALS['egw_info']['server']['change_pwd_every_x_days'] &&
+ ($GLOBALS['egw_info']['user']['apps']['preferences'] || $GLOBALS['egw_info']['user']['apps']['password']) &&
+ egw_time::to('now','ts')-($GLOBALS['egw_info']['server']['change_pwd_every_x_days']*86400)>$GLOBALS['egw_info']['user']['account_lastpwd_change']
+ ) || $GLOBALS['egw_info']['user']['account_lastpwd_change']==0)
+ )
+ {
+ error_log(__METHOD__.' Password of '.$GLOBALS['egw_info']['user']['account_lid'].' ('.$GLOBALS['egw_info']['user']['account_fullname'].') is of old age.'.array2string(array(
+ 'ts'=>$GLOBALS['egw_info']['user']['account_lastpwd_change'],
+ 'date'=>egw_time::to($GLOBALS['egw_info']['user']['account_lastpwd_change']))));
+ if ($GLOBALS['egw_info']['user']['account_lastpwd_change']==0)
+ {
+ $message = lang('an admin required that you must change your password upon login.');
+ }
+ else
+ {
+ $message = lang('it has been more then %1 days since you changed your password',$GLOBALS['egw_info']['server']['change_pwd_every_x_days']);
+ }
+ if ($GLOBALS['egw_info']['user']['apps']['password']) egw::redirect_link('/preferences/password.php',array('message'=>$message));
+ egw::redirect_link('/index.php',array('menuaction'=>'preferences.uipassword.change','message'=>$message));
+ }
+ return true;
+ }
+
/**
* password authentication against password stored in sql datababse
*
@@ -365,29 +405,58 @@ class auth
* @author cornelius weiss
* @return mixed false if password is considered "safe" or a string $message if "unsafe"
*/
- static function crackcheck($passwd)
+ static function crackcheck($passwd,$reqstrength=5)
{
if (!preg_match('/.{'. ($noc=7). ',}/',$passwd))
{
- $message = lang('Password must have at least %1 characters',$noc). ' ';
+ $message[] = lang('Password must have at least %1 characters',$noc). ' ';
+ }
+ else
+ {
+ $strength++;
}
if(!preg_match('/(.*\d.*){'. ($non=1). ',}/',$passwd))
{
- $message .= lang('Password must contain at least %1 numbers',$non). ' ';
+ $message[] = lang('Password must contain at least %1 numbers',$non). ' ';
+ }
+ else
+ {
+ $strength++;
}
if(!preg_match('/(.*[[:upper:]].*){'. ($nou=1). ',}/',$passwd))
{
- $message .= lang('Password must contain at least %1 uppercase letters',$nou). ' ';
+ $message[] = lang('Password must contain at least %1 uppercase letters',$nou). ' ';
+ }
+ else
+ {
+ $strength++;
}
if(!preg_match('/(.*[[:lower:]].*){'. ($nol=1). ',}/',$passwd))
{
- $message .= lang('Password must contain at least %1 lowercase letters',$nol). ' ';
+ $message[] = lang('Password must contain at least %1 lowercase letters',$nol). ' ';
+ }
+ else
+ {
+ $strength++;
}
if(!preg_match('/(.*[\\!"#$%&\'()*+,-.\/:;<=>?@\[\]\^_ {|}~`].*){'. ($nol=1). ',}/',$passwd))
{
- $message .= lang('Password must contain at least %1 special characters',$nol). ' ';
+ $message[] = lang('Password must contain at least %1 special characters',$nol). ' ';
}
- return $message ? $message : false;
+ else
+ {
+ $strength++;
+ }
+ if (count($message)>0 && $reqstrength>$strength)
+ {
+ $outmessage = lang('Your Password does not meet the required strength. You must meet %1 criteria. You met only %2 criteria. Your Password failed the following criteria:',$reqstrength,$strength);
+ $outmessage .= ' '.implode(' ',$message);
+ }
+ else
+ {
+ $outmessage =false;
+ }
+ return $outmessage ? $outmessage : false;
}
/**
diff --git a/phpgwapi/inc/class.egw_framework.inc.php b/phpgwapi/inc/class.egw_framework.inc.php
index 9db9daf307..c08aa05848 100644
--- a/phpgwapi/inc/class.egw_framework.inc.php
+++ b/phpgwapi/inc/class.egw_framework.inc.php
@@ -362,15 +362,15 @@ abstract class egw_framework
$var['quick_add'] = $this->_get_quick_add();
$var['user_info'] = $this->_user_time_info();
-
- if($GLOBALS['egw_info']['user']['lastpasswd_change'] == 0)
+
+ if($GLOBALS['egw_info']['user']['account_lastpwd_change'] == 0)
{
$api_messages = lang('You are required to change your password during your first login').' '.
lang('Click this image on the navbar: %1','');
}
- elseif($GLOBALS['egw_info']['user']['lastpasswd_change'] < time() - (86400*30))
+ elseif($GLOBALS['egw_info']['server']['change_pwd_every_x_days'] && $GLOBALS['egw_info']['user']['account_lastpwd_change'] < time() - (86400*$GLOBALS['egw_info']['server']['change_pwd_every_x_days']))
{
- $api_messages = lang('it has been more then %1 days since you changed your password',30);
+ $api_messages = lang('it has been more then %1 days since you changed your password',$GLOBALS['egw_info']['server']['change_pwd_every_x_days']);
}
// This is gonna change
diff --git a/preferences/inc/class.uipassword.inc.php b/preferences/inc/class.uipassword.inc.php
index 054f50c16e..6158caaef6 100644
--- a/preferences/inc/class.uipassword.inc.php
+++ b/preferences/inc/class.uipassword.inc.php
@@ -23,6 +23,7 @@ class uipassword
function change()
{
+ //_debug_array($GLOBALS['egw_info']['user']);
$n_passwd = $_POST['n_passwd'];
$n_passwd_2 = $_POST['n_passwd_2'];
$o_passwd_2 = $_POST['o_passwd_2'];
@@ -72,11 +73,23 @@ class uipassword
$errors[] = lang('The two passwords are not the same');
}
+ if($o_passwd == $n_passwd)
+ {
+ $errors[] = lang('Old password and new password are the same. This is invalid. You must enter a new password');
+ }
+
if(!$n_passwd)
{
$errors[] = lang('You must enter a password');
}
- if($GLOBALS['egw_info']['server']['check_save_passwd'] && $error_msg = $GLOBALS['egw']->auth->crackcheck($n_passwd))
+ $strength = ($GLOBALS['egw_info']['server']['force_pwd_strength']?$GLOBALS['egw_info']['server']['force_pwd_strength']:false);
+ //error_log(__METHOD__.__LINE__.' Strength:'.$strength);
+
+ if ($strength && $strength>5) $strength =5;
+ if ($strength && $strength<0) $strength = false;
+ if($GLOBALS['egw_info']['server']['check_save_passwd'] && $strength==false) $strength=5;//old behavior
+ //error_log(__METHOD__.__LINE__.' Strength:'.$strength);
+ if(($GLOBALS['egw_info']['server']['check_save_passwd'] || $strength) && $error_msg = $GLOBALS['egw']->auth->crackcheck($n_passwd,$strength))
{
$errors[] = $error_msg;
}
@@ -104,7 +117,10 @@ class uipassword
{
$GLOBALS['egw']->session->appsession('password','phpgwapi',base64_encode($n_passwd));
$GLOBALS['egw_info']['user']['passwd'] = $n_passwd;
+ $GLOBALS['egw_info']['user']['account_lastpwd_change'] = egw_time::to('now','ts');
+ accounts::cache_invalidate($GLOBALS['egw_info']['user']['account_id']);
egw::invalidate_session_cache();
+ //_debug_array( $GLOBALS['egw_info']['user']);
$GLOBALS['hook_values']['account_id'] = $GLOBALS['egw_info']['user']['account_id'];
$GLOBALS['hook_values']['old_passwd'] = $o_passwd;
$GLOBALS['hook_values']['new_passwd'] = $n_passwd;
diff --git a/preferences/index.php b/preferences/index.php
index 266f314c86..aaaa443281 100755
--- a/preferences/index.php
+++ b/preferences/index.php
@@ -11,12 +11,16 @@
$GLOBALS['egw_info'] = array(
'flags' => array(
+ 'noheader' => true,
+ 'novavbar' => true,
'currentapp' => 'preferences',
'disable_Template_class' => True,
),
);
include('../header.inc.php');
-
+auth::check_password_age('preferences','index');
+$GLOBALS['egw_info']['flags']['nonavbar']=false;
+common::egw_header();
$pref_tpl =& CreateObject('phpgwapi.Template',EGW_APP_TPL);
$templates = Array(
'pref' => 'index.tpl'
|