From 7dfce35bea3e9476358048083ed469b2674b41a4 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Tue, 17 Nov 2009 23:22:19 -0500 Subject: (Theoretically) allow users to change their passwords. I cannot test this... but I hope it works :-) --- .../LdapAuthenticationPlugin.php | 164 ++++++++++++++++++++- plugins/LdapAuthentication/README | 8 +- 2 files changed, 163 insertions(+), 9 deletions(-) (limited to 'plugins') diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php index 865154730..ad5dd3a02 100644 --- a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -46,6 +46,7 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin public $options=null; public $filter=null; public $scope=null; + public $password_encoding=null; public $attributes=array(); function onInitializePlugin(){ @@ -68,10 +69,6 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin function checkPassword($username, $password) { - $ldap = $this->ldap_get_connection(); - if(!$ldap){ - return false; - } $entry = $this->ldap_get_user($username); if(!$entry){ return false; @@ -109,8 +106,38 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin function changePassword($username,$oldpassword,$newpassword) { - //TODO implement this - throw new Exception(_('Sorry, changing LDAP passwords is not supported at this time')); + if(! isset($this->attributes['password']) || !isset($this->password_encoding)){ + //throw new Exception(_('Sorry, changing LDAP passwords is not supported at this time')); + return false; + } + $entry = $this->ldap_get_user($username); + if(!$entry){ + return false; + }else{ + $config = $this->ldap_get_config(); + $config['binddn']=$entry->dn(); + $config['bindpw']=$oldpassword; + if($ldap = $this->ldap_get_connection($config)){ + $entry = $this->ldap_get_user($username,array(),$ldap); + + $newCryptedPassword = $this->hashPassword($newpassword, $this->password_encoding); + if ($newCryptedPassword===false) { + return false; + } + if($this->password_encoding=='ad') { + //TODO I believe this code will work once this bug is fixed: http://pear.php.net/bugs/bug.php?id=16796 + $oldCryptedPassword = $this->hashPassword($oldpassword, $this->password_encoding); + $entry->delete( array($this->attributes['password'] => $oldCryptedPassword )); + } + $entry->replace( array($this->attributes['password'] => $newCryptedPassword ), true); + if( Net_LDAP2::isError($entry->upate()) ) { + return false; + } + return true; + }else{ + return false; + } + } return false; } @@ -153,8 +180,10 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin * $param array $attributes LDAP attributes to retrieve * @return string DN */ - function ldap_get_user($username,$attributes=array()){ - $ldap = $this->ldap_get_connection(); + function ldap_get_user($username,$attributes=array(),$ldap=null){ + if($ldap==null) { + $ldap = $this->ldap_get_connection(); + } $filter = Net_LDAP2_Filter::create($this->attributes['username'], 'equals', $username); $options = array( 'scope' => 'sub', @@ -177,4 +206,123 @@ class LdapAuthenticationPlugin extends AuthenticationPlugin return false; } } + + /** + * Code originaly from the phpLDAPadmin development team + * http://phpldapadmin.sourceforge.net/ + * + * Hashes a password and returns the hash based on the specified enc_type. + * + * @param string $passwordClear The password to hash in clear text. + * @param string $encodageType Standard LDAP encryption type which must be one of + * crypt, ext_des, md5crypt, blowfish, md5, sha, smd5, ssha, or clear. + * @return string The hashed password. + * + */ + + function hashPassword( $passwordClear, $encodageType ) + { + $encodageType = strtolower( $encodageType ); + switch( $encodageType ) { + case 'crypt': + $cryptedPassword = '{CRYPT}' . crypt($passwordClear,$this->randomSalt(2)); + break; + + case 'ext_des': + // extended des crypt. see OpenBSD crypt man page. + if ( ! defined( 'CRYPT_EXT_DES' ) || CRYPT_EXT_DES == 0 ) {return FALSE;} //Your system crypt library does not support extended DES encryption. + $cryptedPassword = '{CRYPT}' . crypt( $passwordClear, '_' . $this->randomSalt(8) ); + break; + + case 'md5crypt': + if( ! defined( 'CRYPT_MD5' ) || CRYPT_MD5 == 0 ) {return FALSE;} //Your system crypt library does not support md5crypt encryption. + $cryptedPassword = '{CRYPT}' . crypt( $passwordClear , '$1$' . $this->randomSalt(9) ); + break; + + case 'blowfish': + if( ! defined( 'CRYPT_BLOWFISH' ) || CRYPT_BLOWFISH == 0 ) {return FALSE;} //Your system crypt library does not support blowfish encryption. + $cryptedPassword = '{CRYPT}' . crypt( $passwordClear , '$2a$12$' . $this->randomSalt(13) ); // hardcoded to second blowfish version and set number of rounds + break; + + case 'md5': + $cryptedPassword = '{MD5}' . base64_encode( pack( 'H*' , md5( $passwordClear) ) ); + break; + + case 'sha': + if( function_exists('sha1') ) { + // use php 4.3.0+ sha1 function, if it is available. + $cryptedPassword = '{SHA}' . base64_encode( pack( 'H*' , sha1( $passwordClear) ) ); + } elseif( function_exists( 'mhash' ) ) { + $cryptedPassword = '{SHA}' . base64_encode( mhash( MHASH_SHA1, $passwordClear) ); + } else { + return FALSE; //Your PHP install does not have the mhash() function. Cannot do SHA hashes. + } + break; + + case 'ssha': + if( function_exists( 'mhash' ) && function_exists( 'mhash_keygen_s2k' ) ) { + mt_srand( (double) microtime() * 1000000 ); + $salt = mhash_keygen_s2k( MHASH_SHA1, $passwordClear, substr( pack( "h*", md5( mt_rand() ) ), 0, 8 ), 4 ); + $cryptedPassword = "{SSHA}".base64_encode( mhash( MHASH_SHA1, $passwordClear.$salt ).$salt ); + } else { + return FALSE; //Your PHP install does not have the mhash() function. Cannot do SHA hashes. + } + break; + + case 'smd5': + if( function_exists( 'mhash' ) && function_exists( 'mhash_keygen_s2k' ) ) { + mt_srand( (double) microtime() * 1000000 ); + $salt = mhash_keygen_s2k( MHASH_MD5, $passwordClear, substr( pack( "h*", md5( mt_rand() ) ), 0, 8 ), 4 ); + $cryptedPassword = "{SMD5}".base64_encode( mhash( MHASH_MD5, $passwordClear.$salt ).$salt ); + } else { + return FALSE; //Your PHP install does not have the mhash() function. Cannot do SHA hashes. + } + break; + + case 'ad': + $cryptedPassword = ''; + $passwordClear = "\"" . $passwordClear . "\""; + $len = strlen($passwordClear); + for ($i = 0; $i < $len; $i++) { + $cryptedPassword .= "{$passwordClear{$i}}\000"; + } + + case 'clear': + default: + $cryptedPassword = $passwordClear; + } + + return $cryptedPassword; + } + + /** + * Code originaly from the phpLDAPadmin development team + * http://phpldapadmin.sourceforge.net/ + * + * Used to generate a random salt for crypt-style passwords. Salt strings are used + * to make pre-built hash cracking dictionaries difficult to use as the hash algorithm uses + * not only the user's password but also a randomly generated string. The string is + * stored as the first N characters of the hash for reference of hashing algorithms later. + * + * --- added 20021125 by bayu irawan --- + * --- ammended 20030625 by S C Rigler --- + * + * @param int $length The length of the salt string to generate. + * @return string The generated salt string. + */ + + function randomSalt( $length ) + { + $possible = '0123456789'. + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + './'; + $str = ""; + mt_srand((double)microtime() * 1000000); + + while( strlen( $str ) < $length ) + $str .= substr( $possible, ( rand() % strlen( $possible ) ), 1 ); + + return $str; + } } diff --git a/plugins/LdapAuthentication/README b/plugins/LdapAuthentication/README index dc3f4ba88..2226159c2 100644 --- a/plugins/LdapAuthentication/README +++ b/plugins/LdapAuthentication/README @@ -18,6 +18,9 @@ email_changeable (true): Are users allowed to change their email address? (true or false) password_changeable (true): Are users allowed to change their passwords? (true or false) +password_encoding: required if users are to be able to change their passwords + Possible values are: crypt, ext_des, md5crypt, blowfish, md5, sha, ssha, + smd5, ad, clear host*: LDAP server name to connect to. You can provide several hosts in an array in which case the hosts are tried from left to right. @@ -47,6 +50,7 @@ attributes: an array that relates StatusNet user attributes to LDAP ones fullname homepage location + password: required if users are to be able to change their passwords * required default values are in (parenthesis) @@ -67,10 +71,12 @@ addPlugin('ldapAuthentication', array( 'bindpw'=>'password', 'basedn'=>'OU=Users,OU=StatusNet,OU=US,DC=americas,DC=global,DC=loc', 'host'=>array('server1', 'server2'), + 'password_encoding'=>'ad', 'attributes'=>array( 'username'=>'sAMAccountName', 'nickname'=>'sAMAccountName', 'email'=>'mail', - 'fullname'=>'displayName') + 'fullname'=>'displayName', + 'password'=>'unicodePwd') )); -- cgit v1.2.3-54-g00ecf From 730b1a211f9d28dc33c67cacfda8538ec7196e8f Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 18 Nov 2009 10:42:43 +0000 Subject: Added on click event to open up anchors in notice items in a new window for the Realtime plugin's pop-up window. --- plugins/Realtime/realtimeupdate.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index 9b9991b9e..3a1e9683f 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -208,6 +208,12 @@ RealtimeUpdate = { 'left':'auto', 'right':'0' }); + + $('.notices .entry-title a, .notices .entry-content a').bind('click', function() { + window.open(this.href, ''); + + return false; + }); } } -- cgit v1.2.3-54-g00ecf From edf9b38637cd48b45c9675247bb3243138d98ffb Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 18 Nov 2009 10:43:55 +0000 Subject: Changed window open name to '' because IE doesn't compute names that include the '-' character. --- plugins/Realtime/realtimeupdate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index 3a1e9683f..aa4c6c15f 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -180,7 +180,7 @@ RealtimeUpdate = { RT.click(function() { window.open(url, - timeline, + '', 'toolbar=no,resizable=yes,scrollbars=yes,status=yes,width=500,height=550'); return false; -- cgit v1.2.3-54-g00ecf From 4fbb6b0dfb9ee74accd23d680d45d1cace91974a Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 18 Nov 2009 10:46:55 +0000 Subject: Removed setTimeout. It was initially intended to prevent dupes but this is not the case with 0.9.x's util.js as opposed to 0.8.x, where it didn't properly check if a given notice id is already in the list --- plugins/Realtime/realtimeupdate.js | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index aa4c6c15f..165888054 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -58,23 +58,21 @@ RealtimeUpdate = { receive: function(data) { - setTimeout(function() { - id = data.id; - - // Don't add it if it already exists - if ($("#notice-"+id).length > 0) { - return; - } - - var noticeItem = RealtimeUpdate.makeNoticeItem(data); - $("#notices_primary .notices").prepend(noticeItem); - $("#notices_primary .notice:first").css({display:"none"}); - $("#notices_primary .notice:first").fadeIn(1000); - SN.U.NoticeReply(); - - RealtimeUpdate._updatecounter += 1; - document.title = '('+RealtimeUpdate._updatecounter+') ' + DT; - }, 500); + id = data.id; + + // Don't add it if it already exists + if ($("#notice-"+id).length > 0) { + return; + } + + var noticeItem = RealtimeUpdate.makeNoticeItem(data); + $("#notices_primary .notices").prepend(noticeItem); + $("#notices_primary .notice:first").css({display:"none"}); + $("#notices_primary .notice:first").fadeIn(1000); + SN.U.NoticeReply(); + + RealtimeUpdate._updatecounter += 1; + document.title = '('+RealtimeUpdate._updatecounter+') ' + DT; }, makeNoticeItem: function(data) -- cgit v1.2.3-54-g00ecf From 5e0fb1ddfc877cec5b367857a58f621f47067ddc Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 18 Nov 2009 10:49:41 +0000 Subject: Added a call to NoticeFavor() --- plugins/Realtime/realtimeupdate.js | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index 165888054..3c5d37f79 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -70,6 +70,7 @@ RealtimeUpdate = { $("#notices_primary .notice:first").css({display:"none"}); $("#notices_primary .notice:first").fadeIn(1000); SN.U.NoticeReply(); + SN.U.NoticeFavor(); RealtimeUpdate._updatecounter += 1; document.title = '('+RealtimeUpdate._updatecounter+') ' + DT; -- cgit v1.2.3-54-g00ecf From 0c81f39bee37e288ad6d56091884da61b96637c5 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 18 Nov 2009 10:53:48 +0000 Subject: Added check to see whether window has focus --- plugins/Realtime/realtimeupdate.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index 3c5d37f79..d77a95f7a 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -34,6 +34,7 @@ RealtimeUpdate = { _favorurl: '', _deleteurl: '', _updatecounter: 0, + _windowhasfocus: false, init: function(userid, replyurl, favorurl, deleteurl) { @@ -44,6 +45,8 @@ RealtimeUpdate = { DT = document.title; + $(window).bind('focus', function(){ RealtimeUpdate._windowhasfocus = true; }); + $(window).blur(function() { $('#notices_primary .notice').removeClass('mark-top'); @@ -51,6 +54,7 @@ RealtimeUpdate = { RealtimeUpdate._updatecounter = 0; document.title = DT; + RealtimeUpdate._windowhasfocus = false; return false; }); @@ -72,8 +76,10 @@ RealtimeUpdate = { SN.U.NoticeReply(); SN.U.NoticeFavor(); - RealtimeUpdate._updatecounter += 1; - document.title = '('+RealtimeUpdate._updatecounter+') ' + DT; + if (RealtimeUpdate._windowhasfocus === false) { + RealtimeUpdate._updatecounter += 1; + document.title = '('+RealtimeUpdate._updatecounter+') ' + DT; + } }, makeNoticeItem: function(data) -- cgit v1.2.3-54-g00ecf From 23367ecdcf3146fe4a8d294e95d908f9c4882361 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 18 Nov 2009 10:54:57 +0000 Subject: Setting max notice count in order not to freak out the browser with memory issues. It removes the node and unbinds the previously assigned events. --- plugins/Realtime/realtimeupdate.js | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index d77a95f7a..8e7383a02 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -34,6 +34,7 @@ RealtimeUpdate = { _favorurl: '', _deleteurl: '', _updatecounter: 0, + _maxnotices: 50, _windowhasfocus: false, init: function(userid, replyurl, favorurl, deleteurl) @@ -73,6 +74,14 @@ RealtimeUpdate = { $("#notices_primary .notices").prepend(noticeItem); $("#notices_primary .notice:first").css({display:"none"}); $("#notices_primary .notice:first").fadeIn(1000); + + if ($('#notices_primary .notice').length > RealtimeUpdate._maxnotices) { + $("#notices_primary .notice:last .form_disfavor").unbind('submit'); + $("#notices_primary .notice:last .form_favor").unbind('submit'); + $("#notices_primary .notice:last .notice_reply").unbind('click'); + $("#notices_primary .notice:last").remove(); + } + SN.U.NoticeReply(); SN.U.NoticeFavor(); -- cgit v1.2.3-54-g00ecf From 51e4a45161f0f1cb1a63c3ac5b8748706876bed1 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 18 Nov 2009 10:56:25 +0000 Subject: Changed from click to bind --- plugins/Realtime/realtimeupdate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index 8e7383a02..4444d801d 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -192,7 +192,7 @@ RealtimeUpdate = { }); $('#showstream #notices_primary').css({'margin-top':'18px'}); - RT.click(function() { + RT.bind('click', function() { window.open(url, '', 'toolbar=no,resizable=yes,scrollbars=yes,status=yes,width=500,height=550'); -- cgit v1.2.3-54-g00ecf From 007418fdab8f9f0c718a18568bfbf4377bb85364 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 18 Nov 2009 12:46:36 +0000 Subject: Setting windowhasfocus to true by default --- plugins/Realtime/realtimeupdate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/Realtime/realtimeupdate.js b/plugins/Realtime/realtimeupdate.js index 4444d801d..d1cf1d507 100644 --- a/plugins/Realtime/realtimeupdate.js +++ b/plugins/Realtime/realtimeupdate.js @@ -35,7 +35,7 @@ RealtimeUpdate = { _deleteurl: '', _updatecounter: 0, _maxnotices: 50, - _windowhasfocus: false, + _windowhasfocus: true, init: function(userid, replyurl, favorurl, deleteurl) { @@ -48,7 +48,7 @@ RealtimeUpdate = { $(window).bind('focus', function(){ RealtimeUpdate._windowhasfocus = true; }); - $(window).blur(function() { + $(window).bind('blur', function() { $('#notices_primary .notice').removeClass('mark-top'); $('#notices_primary .notice:first').addClass('mark-top'); -- cgit v1.2.3-54-g00ecf