123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- <?php
- if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
- }
- set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/extlib');
- class LdapCommon
- {
- protected static $ldap_connections = array();
- public $host=null;
- public $port=null;
- public $version=null;
- public $starttls=null;
- public $binddn=null;
- public $bindpw=null;
- public $basedn=null;
- public $options=null;
- public $filter=null;
- public $scope=null;
- public $uniqueMember_attribute = null;
- public $attributes=array();
- public $password_encoding=null;
- public function __construct($config)
- {
- Event::addHandler('Autoload',array($this,'onAutoload'));
- foreach($config as $key=>$value) {
- $this->$key = $value;
- }
- $this->ldap_config = $this->get_ldap_config();
- if(!isset($this->host)){
-
- throw new Exception(_m('A host must be specified.'));
- }
- if(!isset($this->basedn)){
-
- throw new Exception(_m('"basedn" must be specified.'));
- }
- if(!isset($this->attributes['username'])){
-
- throw new Exception(_m('The username attribute must be set.'));
- }
- }
- function onAutoload($cls)
- {
-
- switch ($cls)
- {
- case 'MemcacheSchemaCache':
- require_once(INSTALLDIR.'/plugins/LdapCommon/MemcacheSchemaCache.php');
- return false;
- case 'Net_LDAP2':
- require_once 'Net/LDAP2.php';
- return false;
- case 'Net_LDAP2_Filter':
- require_once 'Net/LDAP2/Filter.php';
- return false;
- case 'Net_LDAP2_Filter':
- require_once 'Net/LDAP2/Filter.php';
- return false;
- case 'Net_LDAP2_Entry':
- require_once 'Net/LDAP2/Entry.php';
- return false;
- }
- return true;
- }
- function get_ldap_config(){
- $config = array();
- $keys = array('host','port','version','starttls','binddn','bindpw','basedn','options','filter','scope');
- foreach($keys as $key){
- $value = $this->$key;
- if($value!==null){
- $config[$key]=$value;
- }
- }
- return $config;
- }
- function get_ldap_connection($config = null){
- if($config == null) {
- $config = $this->ldap_config;
- }
- $config_id = crc32(serialize($config));
- if(array_key_exists($config_id,self::$ldap_connections)) {
- $ldap = self::$ldap_connections[$config_id];
- } else {
-
-
-
- $ldap = new Net_LDAP2($config);
- $ldap->setErrorHandling(PEAR_ERROR_RETURN);
- $err=$ldap->bind();
- if (Net_LDAP2::isError($err)) {
-
-
- if (isset($config) && $err->getCode() == 0x31) {
-
-
- throw new LdapInvalidCredentialsException(sprintf(_m('Could not connect to LDAP server: %s'),$err->getMessage()));
- }
-
-
- throw new Exception(sprintf(_m('Could not connect to LDAP server: %s.'),$err->getMessage()));
- }
- $c = Cache::instance();
- if (!empty($c)) {
- $cacheObj = new MemcacheSchemaCache(
- array('c'=>$c,
- 'cacheKey' => Cache::key('ldap_schema:' . $config_id)));
- $ldap->registerSchemaCache($cacheObj);
- }
- self::$ldap_connections[$config_id] = $ldap;
- }
- return $ldap;
- }
- function checkPassword($username, $password)
- {
- $entry = $this->get_user($username,array('dn' => 'dn'));
- if(!$entry){
- return false;
- }else{
- if(empty($password)) {
-
-
-
- return false;
- }
- $config = $this->get_ldap_config();
- $config['binddn']=$entry->dn();
- $config['bindpw']=$password;
- try {
- $this->get_ldap_connection($config);
- } catch (LdapInvalidCredentialsException $e) {
- return false;
- }
- return true;
- }
- }
- function changePassword($username,$oldpassword,$newpassword)
- {
- if(! isset($this->attributes['password']) || !isset($this->password_encoding)){
-
- return false;
- }
- $entry = $this->get_user($username,array('dn' => 'dn'));
- if(!$entry){
- return false;
- }else{
- $config = $this->get_ldap_config();
- $config['binddn']=$entry->dn();
- $config['bindpw']=$oldpassword;
- try {
- $ldap = $this->get_ldap_connection($config);
- $entry = $this->get_user($username,array(),$ldap);
- $newCryptedPassword = $this->hashPassword($newpassword, $this->password_encoding);
- if ($newCryptedPassword===false) {
- return false;
- }
- if($this->password_encoding=='ad') {
-
- $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;
- } catch (LdapInvalidCredentialsException $e) {
- return false;
- }
- }
- return false;
- }
- function is_dn_member_of_group($userDn, $groupDn)
- {
- $ldap = $this->get_ldap_connection();
- $link = $ldap->getLink();
- $r = @ldap_compare($link, $groupDn, $this->uniqueMember_attribute, $userDn);
- if ($r === true){
- return true;
- }else if($r === false){
- return false;
- }else{
- common_log(LOG_ERR, "LDAP error determining if userDn=$userDn is a member of groupDn=$groupDn using uniqueMember_attribute=$this->uniqueMember_attribute error: ".ldap_error($link));
- return false;
- }
- }
-
- function get_user($username,$attributes=array()){
- $ldap = $this->get_ldap_connection();
- $filter = Net_LDAP2_Filter::create($this->attributes['username'], 'equals', $username);
- $options = array(
- 'attributes' => $attributes
- );
- $search = $ldap->search(null,$filter,$options);
- if (PEAR::isError($search)) {
- common_log(LOG_WARNING, 'Error while getting DN for user: '.$search->getMessage());
- return false;
- }
- if($search->count()==0){
- return false;
- }else if($search->count()==1){
- $entry = $search->shiftEntry();
- return $entry;
- }else{
- common_log(LOG_WARNING, 'Found ' . $search->count() . ' ldap user with the username: ' . $username);
- return false;
- }
- }
-
- function hashPassword( $passwordClear, $encodageType )
- {
- $encodageType = strtolower( $encodageType );
- switch( $encodageType ) {
- case 'crypt':
- $cryptedPassword = '{CRYPT}' . crypt($passwordClear,$this->randomSalt(2));
- break;
- case 'ext_des':
-
- if ( ! defined( 'CRYPT_EXT_DES' ) || CRYPT_EXT_DES == 0 ) {return FALSE;}
- $cryptedPassword = '{CRYPT}' . crypt( $passwordClear, '_' . $this->randomSalt(8) );
- break;
- case 'md5crypt':
- if( ! defined( 'CRYPT_MD5' ) || CRYPT_MD5 == 0 ) {return FALSE;}
- $cryptedPassword = '{CRYPT}' . crypt( $passwordClear , '$1$' . $this->randomSalt(9) );
- break;
- case 'blowfish':
- if( ! defined( 'CRYPT_BLOWFISH' ) || CRYPT_BLOWFISH == 0 ) {return FALSE;}
- $cryptedPassword = '{CRYPT}' . crypt( $passwordClear , '$2a$12$' . $this->randomSalt(13) );
- break;
- case 'md5':
- $cryptedPassword = '{MD5}' . base64_encode( pack( 'H*' , md5( $passwordClear) ) );
- break;
- case 'sha':
- if( function_exists('sha1') ) {
-
- $cryptedPassword = '{SHA}' . base64_encode( pack( 'H*' , sha1( $passwordClear) ) );
- } elseif( function_exists( 'mhash' ) ) {
- $cryptedPassword = '{SHA}' . base64_encode( mhash( MHASH_SHA1, $passwordClear) );
- } else {
- return FALSE;
- }
- 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;
- }
- 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;
- }
- 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;
- }
-
- 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;
- }
- }
- class LdapInvalidCredentialsException extends Exception
- {
- }
|