mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-25 01:13:25 +01:00
* API: full support of active directory as account storage, tested so far with Samba4
This commit is contained in:
parent
f993f20723
commit
4037993dc5
150
addressbook/inc/class.addressbook_ads.inc.php
Normal file
150
addressbook/inc/class.addressbook_ads.inc.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/**
|
||||
* Addressbook - ADS Backend
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <rb@stylite.de>
|
||||
* @package addressbook
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Active directory backend for accounts (not yet AD contacts)
|
||||
*
|
||||
* We use ADS objectGUID as contact ID and UID.
|
||||
*
|
||||
* All values used to construct filters need to run through ldap::quote(),
|
||||
* to be save against LDAP query injection!!!
|
||||
*
|
||||
* @todo get saving of contacts working: fails while checking of container exists ...
|
||||
*/
|
||||
class addressbook_ads extends addressbook_ldap
|
||||
{
|
||||
/**
|
||||
* LDAP searches only a limited set of attributes for performance reasons,
|
||||
* you NEED an index for that columns, ToDo: make it configurable
|
||||
* minimum: $this->columns_to_search = array('n_family','n_given','org_name','email');
|
||||
*/
|
||||
var $search_attributes = array(
|
||||
'n_family','n_middle','n_given','org_name','org_unit',
|
||||
'adr_one_location','note','email','samaccountname',
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter used for accounts addressbook
|
||||
* @var string
|
||||
*/
|
||||
var $accountsFilter = '(objectclass=user)';
|
||||
|
||||
/**
|
||||
* Accounts ADS object
|
||||
*
|
||||
* @var accounts_ads
|
||||
*/
|
||||
protected $accounts_ads;
|
||||
|
||||
/**
|
||||
* constructor of the class
|
||||
*
|
||||
* @param array $ldap_config=null default use from $GLOBALS['egw_info']['server']
|
||||
* @param resource $ds=null ldap connection to use
|
||||
*/
|
||||
function __construct(array $ldap_config=null, $ds=null)
|
||||
{
|
||||
//$this->db_data_cols = $this->stock_contact_fields + $this->non_contact_fields;
|
||||
$this->accountName = $GLOBALS['egw_info']['user']['account_lid'];
|
||||
|
||||
if ($ldap_config)
|
||||
{
|
||||
$this->ldap_config = $ldap_config;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->ldap_config =& $GLOBALS['egw_info']['server'];
|
||||
}
|
||||
|
||||
$this->accounts_ads = $GLOBALS['egw']->accounts->backend;
|
||||
//$this->personalContactsDN = 'ou=personal,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
|
||||
//$this->sharedContactsDN = 'ou=shared,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
|
||||
$this->allContactsDN = $this->accountContactsDN = $this->accounts_ads->ads_context();
|
||||
|
||||
if ($ds)
|
||||
{
|
||||
$this->ds = $ds;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->connect();
|
||||
}
|
||||
$this->ldapServerInfo = ldapserverinfo::get($this->ds, $this->ldap_config['ads_host']);
|
||||
|
||||
// AD seems to use user, instead of inetOrgPerson
|
||||
$this->schema2egw['user'] = $this->schema2egw['inetorgperson'];
|
||||
$this->schema2egw['user'] += array(
|
||||
'account_id' => 'objectsid',
|
||||
'account_lid' => 'samaccountname',
|
||||
'contact_uid' => 'objectguid',
|
||||
);
|
||||
|
||||
foreach($this->schema2egw as $schema => $attributes)
|
||||
{
|
||||
$this->all_attributes = array_merge($this->all_attributes,array_values($attributes));
|
||||
}
|
||||
$this->all_attributes = array_values(array_unique($this->all_attributes));
|
||||
|
||||
$this->charset = translation::charset();
|
||||
}
|
||||
|
||||
/**
|
||||
* connect to LDAP server
|
||||
*
|
||||
* @param boolean $admin=false true (re-)connect with admin not user credentials, eg. to modify accounts
|
||||
*/
|
||||
function connect($admin=false)
|
||||
{
|
||||
$this->ds = $this->accounts_ads->ldap_connection();
|
||||
}
|
||||
|
||||
/**
|
||||
* reads contact data
|
||||
*
|
||||
* @param string/array $contact_id contact_id or array with values for id or account_id
|
||||
* @return array/boolean data if row could be retrived else False
|
||||
*/
|
||||
function read($contact_id)
|
||||
{
|
||||
if (is_array($contact_id) && isset($contact_id['account_id']) ||
|
||||
!is_array($contact_id) && substr($contact_id,0,8) == 'account:')
|
||||
{
|
||||
$account_id = (int)(is_array($contact_id) ? $contact_id['account_id'] : substr($contact_id,8));
|
||||
$contact_id = $GLOBALS['egw']->accounts->id2name($account_id, 'person_id');
|
||||
}
|
||||
$contact_id = ldap::quote(!is_array($contact_id) ? $contact_id :
|
||||
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']));
|
||||
|
||||
$rows = $this->_searchLDAP($this->allContactsDN, "(objectguid=$contact_id)", $this->all_attributes, ADDRESSBOOK_ALL);
|
||||
|
||||
return $rows ? $rows[0] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special handling for mapping data of ADA user objectclass to eGW contact
|
||||
*
|
||||
* Please note: all regular fields are already copied!
|
||||
*
|
||||
* @internal
|
||||
* @param array &$contact already copied fields according to the mapping
|
||||
* @param array $data eGW contact data
|
||||
*/
|
||||
function _user2egw(&$contact, $data)
|
||||
{
|
||||
$contact['account_id'] = $this->accounts_ads->objectsid2account_id($data['objectsid']);
|
||||
$contact['id'] = $contact['contact_uid'] = $this->accounts_ads->objectguid2str($data['objectguid']);
|
||||
|
||||
// ignore system accounts
|
||||
if ($contact['account_id'] < accounts_ads::MIN_ACCOUNT_ID) return false;
|
||||
|
||||
$this->_inetorgperson2egw($contact, $data);
|
||||
}
|
||||
}
|
@ -59,6 +59,22 @@ class addressbook_ldap
|
||||
*/
|
||||
var $sharedContactsDN;
|
||||
|
||||
/**
|
||||
* @var string $accountContactsDN holds the base DN for accounts addressbook
|
||||
*/
|
||||
var $accountContactsDN;
|
||||
|
||||
/**
|
||||
* Filter used for accounts addressbook
|
||||
* @var string
|
||||
*/
|
||||
var $accountsFilter = '(objectclass=posixaccount)';
|
||||
|
||||
/**
|
||||
* @var string $allContactsDN holds the base DN of all addressbook
|
||||
*/
|
||||
var $allContactsDN;
|
||||
|
||||
/**
|
||||
* @var int $total holds the total count of found rows
|
||||
*/
|
||||
@ -71,6 +87,17 @@ class addressbook_ldap
|
||||
*/
|
||||
var $charset;
|
||||
|
||||
/**
|
||||
* LDAP searches only a limited set of attributes for performance reasons,
|
||||
* you NEED an index for that columns, ToDo: make it configurable
|
||||
* minimum: $this->columns_to_search = array('n_family','n_given','org_name','email');
|
||||
*/
|
||||
var $search_attributes = array(
|
||||
'n_family','n_middle','n_given','org_name','org_unit',
|
||||
'adr_one_location','adr_two_location','note',
|
||||
'email','mozillasecondemail','uidnumber',
|
||||
);
|
||||
|
||||
/**
|
||||
* maps between diverse ldap schema and the eGW internal names
|
||||
*
|
||||
@ -82,6 +109,7 @@ class addressbook_ldap
|
||||
'posixaccount' => array(
|
||||
'account_id' => 'uidnumber',
|
||||
'account_lid' => 'uid',
|
||||
'shadowexpire',
|
||||
),
|
||||
'inetorgperson' => array(
|
||||
'n_fn' => 'cn',
|
||||
@ -230,6 +258,8 @@ class addressbook_ldap
|
||||
}
|
||||
$this->personalContactsDN = 'ou=personal,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
|
||||
$this->sharedContactsDN = 'ou=shared,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
|
||||
$this->accountsContactsDN = $this->ldap_config['ldap_context'];
|
||||
$this->allContactsDN = $this->ldap_config['ldap_contact_context'];
|
||||
|
||||
if ($ds)
|
||||
{
|
||||
@ -260,11 +290,17 @@ class addressbook_ldap
|
||||
|
||||
/**
|
||||
* connect to LDAP server
|
||||
*
|
||||
* @param boolean $admin=false true (re-)connect with admin not user credentials, eg. to modify accounts
|
||||
*/
|
||||
function connect()
|
||||
function connect($admin = false)
|
||||
{
|
||||
if ($admin)
|
||||
{
|
||||
$this->ds = $GLOBALS['egw']->ldap->ldapConnect();
|
||||
}
|
||||
// if ldap is NOT the contact repository, we only do accounts and need to use the account-data
|
||||
if (substr($GLOBALS['egw_info']['server']['contact_repository'],-4) != 'ldap') // not (ldap or sql-ldap)
|
||||
elseif (substr($GLOBALS['egw_info']['server']['contact_repository'],-4) != 'ldap') // not (ldap or sql-ldap)
|
||||
{
|
||||
$this->ldap_config['ldap_contact_host'] = $this->ldap_config['ldap_host'];
|
||||
$this->ldap_config['ldap_contact_context'] = $this->ldap_config['ldap_context'];
|
||||
@ -364,10 +400,10 @@ class addressbook_ldap
|
||||
$data['account_id'] == $GLOBALS['egw_info']['user']['account_id']))
|
||||
{
|
||||
// account
|
||||
$baseDN = $this->ldap_config['ldap_context'];
|
||||
$baseDN = $this->accountContactsDN;
|
||||
$cn = false;
|
||||
// we need an admin connection
|
||||
$this->ds = $GLOBALS['egw']->ldap->ldapConnect();
|
||||
$this->ds = $this->connect(true);
|
||||
|
||||
// for sql-ldap we need to account_lid/uid as id, NOT the contact_id in id!
|
||||
if ($GLOBALS['egw_info']['server']['contact_repository'] == 'sql-ldap')
|
||||
@ -606,7 +642,6 @@ class addressbook_ldap
|
||||
*/
|
||||
function &search($criteria,$only_keys=True,$order_by='',$extra_cols='',$wildcard='',$empty=False,$op='AND',$start=false,$filter=null,$join='',$need_full_no_count=false)
|
||||
{
|
||||
//_debug_array($criteria); print "OrderBY: $order_by";_debug_array($extra_cols);_debug_array($filter);
|
||||
#$order_by = explode(',',$order_by);
|
||||
#$order_by = explode(' ',$order_by);
|
||||
#$sort = $order_by[0];
|
||||
@ -650,20 +685,19 @@ class addressbook_ldap
|
||||
}
|
||||
elseif (!isset($filter['owner']))
|
||||
{
|
||||
$searchDN = $this->ldap_config['ldap_contact_context'];
|
||||
$searchDN = $this->allContactsDN;
|
||||
$addressbookType = ADDRESSBOOK_ALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
$searchDN = $this->ldap_config['ldap_context'];
|
||||
$searchDN = $this->accountContactsDN;
|
||||
$addressbookType = ADDRESSBOOK_ACCOUNTS;
|
||||
}
|
||||
|
||||
// create the search filter
|
||||
switch($addressbookType)
|
||||
{
|
||||
case ADDRESSBOOK_ACCOUNTS:
|
||||
$objectFilter = '(objectclass=posixaccount)';
|
||||
$objectFilter = $this->accountsFilter;
|
||||
break;
|
||||
default:
|
||||
$objectFilter = '(objectclass=inetorgperson)';
|
||||
@ -867,16 +901,14 @@ class addressbook_ldap
|
||||
$this->total = 0;
|
||||
|
||||
$_attributes[] = 'entryUUID';
|
||||
$_attributes[] = 'uid';
|
||||
$_attributes[] = 'uidNumber';
|
||||
$_attributes[] = 'objectClass';
|
||||
$_attributes[] = 'createTimestamp';
|
||||
$_attributes[] = 'modifyTimestamp';
|
||||
$_attributes[] = 'creatorsName';
|
||||
$_attributes[] = 'modifiersName';
|
||||
$_attributes[] = 'shadowExpire';
|
||||
|
||||
//echo "<p>ldap_search($this->ds, $_ldapContext, $_filter, $_attributes, 0, $this->ldapLimit)</p>\n";
|
||||
//echo "<p>ldap_search($this->ds, '$_ldapContext', '$_filter', ".array2string($_attributes).", 0, $this->ldapLimit)</p>\n";
|
||||
|
||||
if($_addressbooktype == ADDRESSBOOK_ALL)
|
||||
{
|
||||
$result = ldap_search($this->ds, $_ldapContext, $_filter, $_attributes, 0, $this->ldapLimit);
|
||||
@ -885,22 +917,13 @@ class addressbook_ldap
|
||||
{
|
||||
$result = @ldap_list($this->ds, $_ldapContext, $_filter, $_attributes, 0, $this->ldapLimit);
|
||||
}
|
||||
if(!$result) return array();
|
||||
|
||||
$entries = ldap_get_entries($this->ds, $result);
|
||||
if(!$result || !$entries = ldap_get_entries($this->ds, $result)) return array();
|
||||
|
||||
$this->total = $entries['count'];
|
||||
$shadowExpireNow = floor((time()-date('Z'))/86400);
|
||||
foreach((array)$entries as $i => $entry)
|
||||
foreach($entries as $i => $entry)
|
||||
{
|
||||
if (!is_int($i)) continue; // eg. count
|
||||
|
||||
// exclude expired or deactivated accounts
|
||||
if (isset($entry['shadowexpire']) && $entry['shadowexpire'][0] <= $shadowExpireNow)
|
||||
{
|
||||
--$this->total;
|
||||
continue;
|
||||
}
|
||||
$contact = array(
|
||||
'id' => $entry['uid'][0] ? $entry['uid'][0] : $entry['entryuuid'][0],
|
||||
'tid' => 'n', // the type id for the addressbook
|
||||
@ -914,7 +937,7 @@ class addressbook_ldap
|
||||
}
|
||||
foreach($this->schema2egw[$objectclass] as $egwFieldName => $ldapFieldName)
|
||||
{
|
||||
if(!empty($entry[$ldapFieldName][0]) && !isset($contact[$egwFieldName]))
|
||||
if(!empty($entry[$ldapFieldName][0]) && !is_int($egwFieldName) && !isset($contact[$egwFieldName]))
|
||||
{
|
||||
$contact[$egwFieldName] = translation::convert($entry[$ldapFieldName][0],'utf-8');
|
||||
}
|
||||
@ -922,7 +945,11 @@ class addressbook_ldap
|
||||
$objectclass2egw = '_'.$objectclass.'2egw';
|
||||
if (method_exists($this,$objectclass2egw))
|
||||
{
|
||||
$this->$objectclass2egw($contact,$entry);
|
||||
if (($ret=$this->$objectclass2egw($contact,$entry)) === false)
|
||||
{
|
||||
--$this->total;
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// read binary jpegphoto only for one result == call by read
|
||||
@ -1003,8 +1030,10 @@ class addressbook_ldap
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//error_log(__METHOD__."('$baseDN') !ldap_read({$this->ds}, '$baseDN', 'objectclass=*') ldap_errno()=".ldap_errno($this->ds).', ldap_error()='.ldap_error($this->ds).get_class($this));
|
||||
if(ldap_errno($this->ds) != 32 || substr($baseDN,0,3) != 'cn=')
|
||||
{
|
||||
error_log(__METHOD__."('$baseDN') baseDN does NOT exist and we cant/wont create it! ldap_errno()=".ldap_errno($this->ds).', ldap_error()='.ldap_error($this->ds));
|
||||
return $this->_error(__LINE__); // baseDN does NOT exist and we cant/wont create it
|
||||
}
|
||||
// create a admin connection to add the needed DN
|
||||
@ -1156,6 +1185,27 @@ class addressbook_ldap
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special handling for mapping data of posixAccount objectclass to eGW contact
|
||||
*
|
||||
* Please note: all regular fields are already copied!
|
||||
*
|
||||
* @internal
|
||||
* @param array &$contact already copied fields according to the mapping
|
||||
* @param array $data eGW contact data
|
||||
*/
|
||||
function _posixaccount2egw(&$contact,$data)
|
||||
{
|
||||
static $shadowExpireNow;
|
||||
if (!isset($shadowExpireNow)) $shadowExpireNow = floor((time()-date('Z'))/86400);
|
||||
|
||||
// exclude expired or deactivated accounts
|
||||
if (isset($data['shadowexpire']) && $data['shadowexpire'][0] <= $shadowExpireNow)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special handling for mapping data of the mozillaAbPersonAlpha objectclass to eGW contact
|
||||
*
|
||||
|
@ -114,16 +114,6 @@ class addressbook_so
|
||||
*/
|
||||
var $memberships;
|
||||
|
||||
/**
|
||||
* LDAP searches only a limited set of attributes for performance reasons,
|
||||
* you NEED an index for that columns, ToDo: make it configurable
|
||||
* minimum: $this->columns_to_search = array('n_family','n_given','org_name','email');
|
||||
*/
|
||||
var $ldap_search_attributes = array(
|
||||
'n_family','n_middle','n_given','org_name','org_unit',
|
||||
'adr_one_location','adr_two_location','note',
|
||||
'email','mozillasecondemail','uidnumber',
|
||||
);
|
||||
/**
|
||||
* In SQL we can search all columns, though a view make on real sense
|
||||
*/
|
||||
@ -232,8 +222,7 @@ class addressbook_so
|
||||
{
|
||||
$this->contact_repository = 'ldap';
|
||||
$this->somain = new addressbook_ldap();
|
||||
|
||||
$this->columns_to_search = $this->ldap_search_attributes;
|
||||
$this->columns_to_search = $this->somain->search_attributes;
|
||||
}
|
||||
else // sql or sql->ldap
|
||||
{
|
||||
@ -250,12 +239,13 @@ class addressbook_so
|
||||
{
|
||||
$this->grants = $this->get_grants($this->user,$contact_app);
|
||||
}
|
||||
if ($this->account_repository == 'ldap' && $this->contact_repository == 'sql')
|
||||
if ($this->account_repository != 'sql' && $this->contact_repository == 'sql')
|
||||
{
|
||||
if ($this->account_repository != $this->contact_repository)
|
||||
{
|
||||
$this->so_accounts = new addressbook_ldap();
|
||||
$this->account_cols_to_search = $this->ldap_search_attributes;
|
||||
$class = 'addressbook_'.$this->account_repository;
|
||||
$this->so_accounts = new $class();
|
||||
$this->account_cols_to_search = $this->so_accounts->search_attributes;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -319,8 +319,7 @@ class accounts
|
||||
$account_search[$serial]['total'] = $this->total;
|
||||
}
|
||||
// search via ldap backend
|
||||
elseif ($this->config['account_repository'] == 'ldap')
|
||||
//not correct for php<5.1 elseif ((method_exists($this,'search')) // implements its on search function ==> use it
|
||||
elseif (method_exists($this->backend, 'search')) // implements its on search function ==> use it
|
||||
{
|
||||
$account_search[$serial]['data'] = $this->backend->search($param);
|
||||
$account_search[$serial]['total'] = $this->total = $this->backend->total;
|
||||
@ -1048,11 +1047,11 @@ class accounts
|
||||
{
|
||||
if ($instance->get_type($account_id) == 'u')
|
||||
{
|
||||
$account['memberships'] = $instance->backend->memberships($account_id);
|
||||
if (!isset($account['memberships'])) $account['memberships'] = $instance->backend->memberships($account_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$account['members'] = $instance->backend->members($account_id);
|
||||
if (!isset($account['members'])) $account['members'] = $instance->backend->members($account_id);
|
||||
}
|
||||
egw_cache::setInstance(__CLASS__, 'account-'.$account_id, $account, self::READ_CACHE_TIMEOUT);
|
||||
}
|
||||
|
1360
phpgwapi/inc/class.accounts_ads.inc.php
Normal file
1360
phpgwapi/inc/class.accounts_ads.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -638,7 +638,7 @@ class accounts_ldap
|
||||
function search($param)
|
||||
{
|
||||
//echo "<p>accounts_ldap::search(".print_r($param,true)."): ".microtime()."</p>\n";
|
||||
$account_search = &$this->cache['account_search'];
|
||||
$account_search =& accounts::$cache['account_search'];
|
||||
|
||||
// check if the query is cached
|
||||
$serial = serialize($param);
|
||||
@ -919,7 +919,7 @@ class accounts_ldap
|
||||
if ($which == 'account_lid' && $account_type !== 'u') // groups only support account_lid
|
||||
{
|
||||
|
||||
$sri = ldap_search($this->ds, $this->group_context, '(&(cn=' . $name . ')(objectclass=posixgroup))');
|
||||
$sri = ldap_search($this->ds, $this->group_context, '(&(cn=' . $name . ')(objectclass=posixgroup))', array('gidNumber'));
|
||||
$allValues = ldap_get_entries($this->ds, $sri);
|
||||
|
||||
if (@$allValues[0]['gidnumber'][0])
|
||||
@ -936,7 +936,7 @@ class accounts_ldap
|
||||
return False;
|
||||
}
|
||||
|
||||
$sri = ldap_search($this->ds, $this->user_context, '(&('.$to_ldap[$which].'=' . $name . ')(objectclass=posixaccount))');
|
||||
$sri = ldap_search($this->ds, $this->user_context, '(&('.$to_ldap[$which].'=' . $name . ')(objectclass=posixaccount))', array('uidNumber'));
|
||||
|
||||
$allValues = ldap_get_entries($this->ds, $sri);
|
||||
|
||||
|
@ -36,42 +36,22 @@ class auth_ads implements auth_backend
|
||||
return False;
|
||||
}
|
||||
|
||||
if(!$ldap = @ldap_connect($GLOBALS['egw_info']['server']['ads_host']))
|
||||
{
|
||||
//echo "<p>Failed connecting to ADS server '".$GLOBALS['egw_info']['server']['ads_host']."' for authenication, execution stopped</p>\n";
|
||||
$GLOBALS['egw']->log->message('F-Abort, Failed connecting to ADS server for authenication, execution stopped');
|
||||
$GLOBALS['egw']->log->commit();
|
||||
return False;
|
||||
}
|
||||
//echo "<p>Connected to LDAP server '".$GLOBALS['egw_info']['server']['ads_host']."' for authenication</p>\n";
|
||||
|
||||
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
|
||||
|
||||
$adldap = accounts_ads::get_adldap();
|
||||
// bind with username@ads_domain, only if a non-empty password given, in case anonymous search is enabled
|
||||
if(empty($passwd) || !@ldap_bind($ldap,$username.'@'.$GLOBALS['egw_info']['server']['ads_domain'],$passwd))
|
||||
if(empty($passwd) || !$adldap->authenticate($username, $passwd))
|
||||
{
|
||||
//echo "<p>Cant bind with '$username@".$GLOBALS['egw_info']['server']['ads_domain']."' with PW '$passwd' !!!</p>\n";
|
||||
//error_log(__METHOD__."('$username', ".(empty($passwd) ? "'') passwd empty" : '$passwd) adldap->authenticate() returned false')." --> returning false");
|
||||
return False;
|
||||
}
|
||||
//echo "<p>Bind with '$username@".$GLOBALS['egw_info']['server']['ads_domain']."' with PW '$passwd'.</p>\n";
|
||||
|
||||
$attributes = array('samaccountname','givenName','sn','mail','homeDirectory');
|
||||
$filter = "(samaccountname=$username)";
|
||||
// automatic create dn from domain: domain.com ==> DC=domain,DC=com
|
||||
$base_dn = array();
|
||||
foreach(explode('.',$GLOBALS['egw_info']['server']['ads_domain']) as $dc)
|
||||
if (($allValues = $adldap->user()->info($username, $attributes)))
|
||||
{
|
||||
$base_dn[] = 'DC='.$dc;
|
||||
$allValues[0]['objectsid'][0] = $adldap->utilities()->getTextSID($allValues[0]['objectsid'][0]);
|
||||
}
|
||||
$base_dn = implode(',',$base_dn);
|
||||
//error_log(__METHOD__."('$username', \$passwd) allValues=".array2string($allValues));
|
||||
|
||||
//echo "<p>Trying ldap_search(,$base_dn,$filter,".print_r($attributes,true)."</p>\n";
|
||||
$sri = ldap_search($ldap, $base_dn, $filter, $attributes);
|
||||
$allValues = ldap_get_entries($ldap, $sri);
|
||||
//_debug_array($allValues);
|
||||
|
||||
if ($allValues['count'] > 0)
|
||||
if ($allValues && $allValues['count'] > 0)
|
||||
{
|
||||
if($GLOBALS['egw_info']['server']['case_sensitive_username'] == true)
|
||||
{
|
||||
@ -92,6 +72,8 @@ class auth_ads implements auth_backend
|
||||
}
|
||||
if ($GLOBALS['egw_info']['server']['auto_create_acct'])
|
||||
{
|
||||
$GLOBALS['auto_create_acct']['account_id'] = accounts_ads::sid2account_id($allValues[0]['objectsid'][0]);
|
||||
|
||||
// create a global array with all availible info about that account
|
||||
foreach(array(
|
||||
'givenname' => 'firstname',
|
||||
@ -102,6 +84,7 @@ class auth_ads implements auth_backend
|
||||
$GLOBALS['auto_create_acct'][$acct_name] =
|
||||
translation::convert($allValues[0][$ldap_name][0],'utf-8');
|
||||
}
|
||||
//error_log(__METHOD__."() \$GLOBALS[auto_create_acct]=".array2string($GLOBALS['auto_create_acct']));
|
||||
return True;
|
||||
}
|
||||
}
|
||||
@ -109,8 +92,38 @@ class auth_ads implements auth_backend
|
||||
return False;
|
||||
}
|
||||
|
||||
/**
|
||||
* changes password
|
||||
*
|
||||
* @param string $old_passwd must be cleartext
|
||||
* @param string $new_passwd must be cleartext
|
||||
* @param int $account_id account id of user whose passwd should be changed
|
||||
* @return boolean true if password successful changed, false otherwise
|
||||
*/
|
||||
function change_password($old_passwd, $new_passwd, $_account_id=0)
|
||||
{
|
||||
if (!($adldap = accounts_ads::get_adldap()) || !($adldap->getUseSSL() || $adldap->getUseTLS()))
|
||||
{
|
||||
error_log(__METHOD__."('$old_passwd', '$new_passwd', $account_id) adldap=".array2string($adldap)." returning false");
|
||||
return false; // Cant change passwd in ADS
|
||||
}
|
||||
|
||||
if(!$account_id || $GLOBALS['egw_info']['flags']['currentapp'] == 'login')
|
||||
{
|
||||
$admin = false;
|
||||
$username = $GLOBALS['egw_info']['user']['account_lid'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$admin = true;
|
||||
$username = $GLOBALS['egw']->accounts->id2name($account_id);
|
||||
}
|
||||
// Check the old_passwd to make sure this is legal
|
||||
if(!$admin && !$adldap->authenticate($username, $old_passwd))
|
||||
{
|
||||
//error_log(__METHOD__."() old password '$old_passwd' for '$username' is wrong!");
|
||||
return false;
|
||||
}
|
||||
return $adldap->user()->password($username, $new_passwd);
|
||||
}
|
||||
}
|
||||
|
@ -96,10 +96,14 @@ else
|
||||
if($_POST['delete_all'])
|
||||
{
|
||||
/* Now, clear out existing tables */
|
||||
foreach(array($GLOBALS['egw_setup']->accounts_table,$GLOBALS['egw_setup']->prefs_table,$GLOBALS['egw_setup']->acl_table,'egw_access_log') as $table)
|
||||
foreach(array($GLOBALS['egw_setup']->accounts_table,$GLOBALS['egw_setup']->acl_table,'egw_access_log') as $table)
|
||||
{
|
||||
$GLOBALS['egw_setup']->db->delete($table,'1=1',__LINE__,__FILE__);
|
||||
}
|
||||
// keep default and forced prefs from installed apps
|
||||
$GLOBALS['egw_setup']->db->delete($GLOBALS['egw_setup']->prefs_table,'preferences_owner NOT IN (-1,-2)',__LINE__,__FILE__);
|
||||
// remove accounts from addressbook
|
||||
$GLOBALS['egw_setup']->db->delete('egw_addressbook','account_id IS NOT NULL',__LINE__,__FILE__);
|
||||
}
|
||||
/* Create the demo groups */
|
||||
$defaultgroupid = (int)$GLOBALS['egw_setup']->add_account('Default','Default','Group',False,False);
|
||||
|
@ -999,7 +999,7 @@ class setup
|
||||
{
|
||||
// load the configuration from the database
|
||||
foreach($this->db->select($this->config_table,'config_name,config_value',
|
||||
"config_name LIKE 'ldap%' OR config_name LIKE 'account_%' OR config_name LIKE '%encryption%' OR config_name='auth_type'",
|
||||
"config_name LIKE 'ads%' OR config_name LIKE 'ldap%' OR config_name LIKE 'account_%' OR config_name LIKE '%encryption%' OR config_name='auth_type'",
|
||||
__LINE__,__FILE__) as $row)
|
||||
{
|
||||
$GLOBALS['egw_info']['server'][$row['config_name']] = $config[$row['config_name']] = $row['config_value'];
|
||||
|
@ -276,7 +276,7 @@
|
||||
<select name="newsettings[account_repository]">
|
||||
<option value="sql"{selected_account_repository_sql}>SQL</option>
|
||||
<option value="ldap"{selected_account_repository_ldap}>LDAP</option>
|
||||
<!--<option value="contacts"{selected_account_repository_contacts}>Contacts - EXPERIMENTAL</option>-->
|
||||
<option value="ads"{selected_account_repository_ads}>Active Directory</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@ -539,6 +539,29 @@
|
||||
<td>{lang_Domain_name}:</td>
|
||||
<td><input name="newsettings[ads_domain]" value="{value_ads_domain}" size="40" /></td>
|
||||
</tr>
|
||||
<tr class="row_off">
|
||||
<td>{lang_Admin_user}<br/>{lang_optional,_if_only_authentication_AND_anonymous_search_is_enabled}:</td>
|
||||
<td><input name="newsettings[ads_admin_user]" value="{value_ads_admin_user}" size="40" /></td>
|
||||
</tr>
|
||||
<tr class="row_on">
|
||||
<td>{lang_Password}:</td>
|
||||
<td><input type="password" name="newsettings[ads_admin_passwd]" value="{value_ads_admin_passwd}" size="40" /></td>
|
||||
</tr>
|
||||
<tr class="row_off">
|
||||
<td>{lang_use_TLS_or_SSL} {lang_required_to_change_passwords}<br/>
|
||||
<a href="http://adldap.sourceforge.net/wiki/doku.php?id=ldap_over_ssl" target="_blank">{lang_needs_extra_configuration_on_DC_and_webserver!}</a>:</td>
|
||||
<td>
|
||||
<select name="newsettings[ads_connection]">
|
||||
<option value="">{lang_No}</option>
|
||||
<option value="tls"{selected_ads_connection_tls}>TLS</option>
|
||||
<option value="ssl"{selected_ads_connection_ssl}>SSL</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row_on">
|
||||
<td>{lang_Context_to_create_users}:<br/>{lang_eg._"CN=Users,DC=domain,DC=com"_for_ADS_domain_"domain.com"}</td>
|
||||
<td><input name="newsettings[ads_context]" value="{value_ads_context}" size="80" /></td>
|
||||
</tr>
|
||||
|
||||
<tr class="row_off">
|
||||
<td colspan="2"> </td>
|
||||
|
Loading…
Reference in New Issue
Block a user