From abb56b33e0993b3c6a7f114fbd074cc59626c394 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 28 Oct 2011 14:24:56 +0200 Subject: Check password expiry times in Active Directory backend When a user logs in, the password expiry time is checked and compared to the $conf['auth']['ad']['expirywarn'] setting (in days). If the password is about to expire in the specified timeframe, a warning is issued on login. This patch adds a new method to the adLDAP class for querying domain parameters. --- inc/adLDAP.php | 20 ++++++++++++++++++++ inc/auth/ad.class.php | 28 +++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 5 deletions(-) (limited to 'inc') diff --git a/inc/adLDAP.php b/inc/adLDAP.php index a64096b85..24be6e475 100644 --- a/inc/adLDAP.php +++ b/inc/adLDAP.php @@ -1020,6 +1020,26 @@ class adLDAP { return (false); } + /** + * Return info about the domain itself + * + * @authot Andreas Gohr + * @param array $fields The fields to query + * @return array + */ + public function domain_info($fields){ + if (!$this->_bind){ return (false); } + + $sr = ldap_read($this->_conn, $this->_base_dn, 'objectclass=*', $fields); + if (!$sr) { + return false; + } + $info = ldap_get_entries($this->_conn, $sr); + if(count($info)) return $info[0]; + + return false; + } + /** * Determine a user's password expiry date * diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index 1fddad243..6b022d217 100644 --- a/inc/auth/ad.class.php +++ b/inc/auth/ad.class.php @@ -26,6 +26,8 @@ * $conf['auth']['ad']['use_ssl'] = 1; * $conf['auth']['ad']['use_tls'] = 1; * $conf['auth']['ad']['debug'] = 1; + * // warn user about expiring password in this mayn days in advance: + * $conf['auth']['ad']['expirywarn'] = 5; * * // get additional information to the userinfo array * // add a list of comma separated ldap contact fields. @@ -148,7 +150,7 @@ class auth_ad extends auth_basic { global $conf; if(!$this->_init()) return false; - $fields = array('mail','displayname','samaccountname'); + $fields = array('mail','displayname','samaccountname','lastpwd','pwdlastset','useraccountcontrol'); // add additional fields to read $fields = array_merge($fields, $this->cnf['additional']); @@ -157,10 +159,14 @@ class auth_ad extends auth_basic { //get info for given user $result = $this->adldap->user_info($user, $fields); //general user info - $info['name'] = $result[0]['displayname'][0]; - $info['mail'] = $result[0]['mail'][0]; - $info['uid'] = $result[0]['samaccountname'][0]; - $info['dn'] = $result[0]['dn']; + $info['name'] = $result[0]['displayname'][0]; + $info['mail'] = $result[0]['mail'][0]; + $info['uid'] = $result[0]['samaccountname'][0]; + $info['dn'] = $result[0]['dn']; + //last password set (Windows counts from January 1st 1601) + $info['lastpwd'] = $result[0]['pwdlastset'][0] / 10000000 - 11644473600; + //will it expire? + $info['expires'] = !($result[0]['useraccountcontrol'][0] & 0x10000); //ADS_UF_DONT_EXPIRE_PASSWD // additional information foreach ($this->cnf['additional'] as $field) { @@ -183,6 +189,18 @@ class auth_ad extends auth_basic { $info['grps'][] = $conf['defaultgroup']; } + // password will expire, let's warn the current user + if($_SERVER['REMOTE_USER'] == $user && $info['expires'] && $this->cnf['expirywarn']){ + $result = $this->adldap->domain_info(array('maxpwdage')); // maximum pass age + $maxage = -1 * $result['maxpwdage'][0] / 10000000; // negative 100 nanosecs + $timeleft = $maxage - (time() - $info['lastpwd']); + $timeleft = round($timeleft/(24*60*60)); + + if($timeleft <= $this->cnf['expirywarn']){ + msg('Your password will expire in '.$timeleft.' days. You should change it.'); + } + } + return $info; } -- cgit v1.2.3 From 22ffffcf6892924895d9ad45f749a307d05e09e0 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 7 Nov 2011 14:15:29 +0100 Subject: always check expire time when configured --- inc/auth/ad.class.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'inc') diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index 6b022d217..c3df2417b 100644 --- a/inc/auth/ad.class.php +++ b/inc/auth/ad.class.php @@ -189,14 +189,16 @@ class auth_ad extends auth_basic { $info['grps'][] = $conf['defaultgroup']; } - // password will expire, let's warn the current user - if($_SERVER['REMOTE_USER'] == $user && $info['expires'] && $this->cnf['expirywarn']){ + // check expiry time + if($info['expires'] && $this->cnf['expirywarn']){ $result = $this->adldap->domain_info(array('maxpwdage')); // maximum pass age $maxage = -1 * $result['maxpwdage'][0] / 10000000; // negative 100 nanosecs $timeleft = $maxage - (time() - $info['lastpwd']); $timeleft = round($timeleft/(24*60*60)); + $info['expiresin'] = $timeleft; - if($timeleft <= $this->cnf['expirywarn']){ + // if this is the current user, warn him + if( ($_SERVER['REMOTE_USER'] == $user) && ($timeleft <= $this->cnf['expirywarn'])){ msg('Your password will expire in '.$timeleft.' days. You should change it.'); } } -- cgit v1.2.3 From 7f99c819166c15279a3214e3439be8efb77f7021 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 7 Nov 2011 14:31:09 +0100 Subject: do not query AD for empty user name --- inc/auth/ad.class.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'inc') diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index c3df2417b..4363cfb07 100644 --- a/inc/auth/ad.class.php +++ b/inc/auth/ad.class.php @@ -150,6 +150,8 @@ class auth_ad extends auth_basic { global $conf; if(!$this->_init()) return false; + if($user == '') return array(); + $fields = array('mail','displayname','samaccountname','lastpwd','pwdlastset','useraccountcontrol'); // add additional fields to read -- cgit v1.2.3 From 9565908d97917c579e2ecb44a0b44a133df598fe Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 7 Nov 2011 14:36:23 +0100 Subject: Don't return any data for non-existant users --- inc/auth/ad.class.php | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'inc') diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index 4363cfb07..678a32047 100644 --- a/inc/auth/ad.class.php +++ b/inc/auth/ad.class.php @@ -160,6 +160,10 @@ class auth_ad extends auth_basic { //get info for given user $result = $this->adldap->user_info($user, $fields); + if($result == false){ + return array(); + } + //general user info $info['name'] = $result[0]['displayname'][0]; $info['mail'] = $result[0]['mail'][0]; -- cgit v1.2.3 From b2117c6969fc31aa958f6019fd1e4e258f555db7 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 7 Nov 2011 14:49:29 +0100 Subject: translatable AD expiry warning and link to update profile page --- inc/auth/ad.class.php | 5 +++-- inc/lang/de/lang.php | 1 + inc/lang/en/lang.php | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'inc') diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index 678a32047..cb59c5a48 100644 --- a/inc/auth/ad.class.php +++ b/inc/auth/ad.class.php @@ -26,7 +26,7 @@ * $conf['auth']['ad']['use_ssl'] = 1; * $conf['auth']['ad']['use_tls'] = 1; * $conf['auth']['ad']['debug'] = 1; - * // warn user about expiring password in this mayn days in advance: + * // warn user about expiring password this many days in advance: * $conf['auth']['ad']['expirywarn'] = 5; * * // get additional information to the userinfo array @@ -148,6 +148,7 @@ class auth_ad extends auth_basic { */ function getUserData($user){ global $conf; + global $lang; if(!$this->_init()) return false; if($user == '') return array(); @@ -205,7 +206,7 @@ class auth_ad extends auth_basic { // if this is the current user, warn him if( ($_SERVER['REMOTE_USER'] == $user) && ($timeleft <= $this->cnf['expirywarn'])){ - msg('Your password will expire in '.$timeleft.' days. You should change it.'); + msg(sprintf($lang['authpwdexpire'],$timeleft)); } } diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php index eef2f6632..8fdffd66e 100644 --- a/inc/lang/de/lang.php +++ b/inc/lang/de/lang.php @@ -268,6 +268,7 @@ $lang['subscr_style_digest'] = 'Zusammenfassung der Änderungen für jede ver $lang['subscr_style_list'] = 'Liste der geänderten Seiten (Alle %.2f Tage)'; $lang['authmodfailed'] = 'Benutzerüberprüfung nicht möglich. Bitte wenden Sie sich an den Systembetreuer.'; $lang['authtempfail'] = 'Benutzerüberprüfung momentan nicht möglich. Falls das Problem andauert, wenden Sie sich an den Systembetreuer.'; +$lang['authpwdexpire'] = 'Ihr Passwort läuft in %d Tag(en) ab. Sie sollten es ändern.'; $lang['i_chooselang'] = 'Wählen Sie Ihre Sprache'; $lang['i_installer'] = 'DokuWiki Installation'; $lang['i_wikiname'] = 'Wiki-Name'; diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 89a7c4d40..9250d119a 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -275,6 +275,7 @@ $lang['subscr_style_list'] = 'list of changed pages since last email (e /* auth.class language support */ $lang['authmodfailed'] = 'Bad user authentication configuration. Please inform your Wiki Admin.'; $lang['authtempfail'] = 'User authentication is temporarily unavailable. If this situation persists, please inform your Wiki Admin.'; +$lang['authpwdexpire'] = 'Your password will expire in %d days. You should change it.'; /* installer strings */ $lang['i_chooselang'] = 'Choose your language'; -- cgit v1.2.3 From 69995a164f9dbb51adfe17f09901e0200ea8dc7a Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 17 Feb 2012 13:39:38 +0100 Subject: do not hardcode profile link in AD pass expire message Changing passwords might not be available. --- inc/auth/ad.class.php | 8 +++++++- inc/lang/de/lang.php | 2 +- inc/lang/en/lang.php | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'inc') diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index cb59c5a48..dc1fef17a 100644 --- a/inc/auth/ad.class.php +++ b/inc/auth/ad.class.php @@ -149,6 +149,7 @@ class auth_ad extends auth_basic { function getUserData($user){ global $conf; global $lang; + global $ID; if(!$this->_init()) return false; if($user == '') return array(); @@ -206,7 +207,12 @@ class auth_ad extends auth_basic { // if this is the current user, warn him if( ($_SERVER['REMOTE_USER'] == $user) && ($timeleft <= $this->cnf['expirywarn'])){ - msg(sprintf($lang['authpwdexpire'],$timeleft)); + $msg = sprintf($lang['authpwdexpire'],$timeleft); + if($this->canDo('modPass')){ + $url = wl($ID,array('do'=>'profile')); + $msg .= ' '.$lang['btn_profile'].''; + } + msg($msg); } } diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php index 8fdffd66e..c7b2d7893 100644 --- a/inc/lang/de/lang.php +++ b/inc/lang/de/lang.php @@ -268,7 +268,7 @@ $lang['subscr_style_digest'] = 'Zusammenfassung der Änderungen für jede ver $lang['subscr_style_list'] = 'Liste der geänderten Seiten (Alle %.2f Tage)'; $lang['authmodfailed'] = 'Benutzerüberprüfung nicht möglich. Bitte wenden Sie sich an den Systembetreuer.'; $lang['authtempfail'] = 'Benutzerüberprüfung momentan nicht möglich. Falls das Problem andauert, wenden Sie sich an den Systembetreuer.'; -$lang['authpwdexpire'] = 'Ihr Passwort läuft in %d Tag(en) ab. Sie sollten es ändern.'; +$lang['authpwdexpire'] = 'Ihr Passwort läuft in %d Tag(en) ab, Sie sollten es bald ändern.'; $lang['i_chooselang'] = 'Wählen Sie Ihre Sprache'; $lang['i_installer'] = 'DokuWiki Installation'; $lang['i_wikiname'] = 'Wiki-Name'; diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 9250d119a..5c8628da5 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -275,7 +275,7 @@ $lang['subscr_style_list'] = 'list of changed pages since last email (e /* auth.class language support */ $lang['authmodfailed'] = 'Bad user authentication configuration. Please inform your Wiki Admin.'; $lang['authtempfail'] = 'User authentication is temporarily unavailable. If this situation persists, please inform your Wiki Admin.'; -$lang['authpwdexpire'] = 'Your password will expire in %d days. You should change it.'; +$lang['authpwdexpire'] = 'Your password will expire in %d days, you should change it soon.'; /* installer strings */ $lang['i_chooselang'] = 'Choose your language'; -- cgit v1.2.3 From 1e5105f90f56d0f57111eff37a535480115920c5 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 17 Feb 2012 13:42:39 +0100 Subject: make sure AD pass expiry message is never shown twice --- inc/auth/ad.class.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'inc') diff --git a/inc/auth/ad.class.php b/inc/auth/ad.class.php index dc1fef17a..cc080dc93 100644 --- a/inc/auth/ad.class.php +++ b/inc/auth/ad.class.php @@ -46,6 +46,7 @@ class auth_ad extends auth_basic { var $opts = null; var $adldap = null; var $users = null; + var $msgshown = false; /** * Constructor @@ -205,14 +206,18 @@ class auth_ad extends auth_basic { $timeleft = round($timeleft/(24*60*60)); $info['expiresin'] = $timeleft; - // if this is the current user, warn him - if( ($_SERVER['REMOTE_USER'] == $user) && ($timeleft <= $this->cnf['expirywarn'])){ + // if this is the current user, warn him (once per request only) + if( ($_SERVER['REMOTE_USER'] == $user) && + ($timeleft <= $this->cnf['expirywarn']) && + !$this->msgshown + ){ $msg = sprintf($lang['authpwdexpire'],$timeleft); if($this->canDo('modPass')){ $url = wl($ID,array('do'=>'profile')); $msg .= ' '.$lang['btn_profile'].''; } msg($msg); + $this->msgshown = true; } } -- cgit v1.2.3