forked from extern/egroupware
allow to update passwords from LDAP, if accounts stored in SQL and authentication is against LDAP
This commit is contained in:
parent
eb2a814c0d
commit
e5b3a83693
@ -66,7 +66,7 @@ array_shift($base_parts);
|
||||
|
||||
$cmd = new setup_cmd_ldap(array(
|
||||
'domain' => $GLOBALS['egw_setup']->ConfigDomain,
|
||||
'sub_command' => 'migrate_to_'.$to,
|
||||
'sub_command' => $_POST['passwords2sql'] ? 'passwords_to_sql' : 'migrate_to_'.$to,
|
||||
// allow to set ldap root DN (ldap_admin) to create instance specific admin DN and structure
|
||||
'ldap_admin' => !empty($_POST['ldap_admin']) ? $_POST['ldap_admin'] : $GLOBALS['egw_info']['server']['ldap_root_dn'],
|
||||
'ldap_admin_pw' => !empty($_POST['ldap_admin']) ? $_POST['ldap_admin_pw'] : $GLOBALS['egw_info']['server']['ldap_root_pw'],
|
||||
@ -74,7 +74,7 @@ $cmd = new setup_cmd_ldap(array(
|
||||
'truncate_egw_accounts' => !empty($_POST['truncate_egw_accounts']),
|
||||
)+$GLOBALS['egw_info']['server']);
|
||||
|
||||
if (!$_POST['migrate'])
|
||||
if (!$_POST['migrate'] && !$_POST['passwords2sql'])
|
||||
{
|
||||
$accounts = $cmd->accounts($from == 'ldap');
|
||||
|
||||
@ -100,7 +100,7 @@ if (!$_POST['migrate'])
|
||||
else
|
||||
{
|
||||
$user_list .= '<option value="' . $account_id . '" selected="1">'.
|
||||
$GLOBALS['egw']->common->display_fullname($account['account_lid'],
|
||||
common::display_fullname($account['account_lid'],
|
||||
$account['account_firstname'],$account['account_lastname']) . "</option>\n";
|
||||
}
|
||||
}
|
||||
@ -119,6 +119,10 @@ if (!$_POST['migrate'])
|
||||
$setup_tpl->set_var('ldap_admin_pw_label', lang('Root DN password'));
|
||||
$setup_tpl->set_var('migrate',$direction);
|
||||
$setup_tpl->set_var('cancel',lang('Cancel'));
|
||||
if ($from == 'sql' && $GLOBALS['egw_info']['server']['auth_type'] == 'ldap')
|
||||
{
|
||||
$setup_tpl->set_var('extra_button', html::submit_button('passwords2sql', lang('Passwords --> SQL')));
|
||||
}
|
||||
|
||||
$setup_tpl->pfp('out','header');
|
||||
if($user_list)
|
||||
@ -143,14 +147,19 @@ if (!$_POST['migrate'])
|
||||
}
|
||||
else // do the migration
|
||||
{
|
||||
$cmd->only = array_merge((array)$_POST['users'],(array)$_POST['groups']);
|
||||
$cmd->only = (array)$_POST['users'];
|
||||
if (empty($_POST['passwords2sql'])) $cmd->only = array_merge($cmd->only, (array)$_POST['groups']);
|
||||
$cmd->verbose = true;
|
||||
echo '<p align="center">'.str_replace("\n","</p>\n<p align='center'>",$cmd->run())."</p>\n";
|
||||
|
||||
// store new repostory (and auth_type), as we are migrated now
|
||||
config::save_value('account_repository', $GLOBALS['egw_info']['server']['account_repository']=$to, 'phpgwapi');
|
||||
if (empty($GLOBALS['egw_info']['server']['auth_type']) || $GLOBALS['egw_info']['server']['auth_type'] == $from)
|
||||
if ($_POST['migrate'])
|
||||
{
|
||||
config::save_value('auth_type', $GLOBALS['egw_info']['server']['auth_type']=$to, 'phpgwapi');
|
||||
config::save_value('account_repository', $GLOBALS['egw_info']['server']['account_repository']=$to, 'phpgwapi');
|
||||
if (empty($GLOBALS['egw_info']['server']['auth_type']) || $GLOBALS['egw_info']['server']['auth_type'] == $from)
|
||||
{
|
||||
config::save_value('auth_type', $GLOBALS['egw_info']['server']['auth_type']=$to, 'phpgwapi');
|
||||
}
|
||||
}
|
||||
echo '<p align="center">'.lang('Click <a href="index.php">here</a> to return to setup.')."</p>\n";
|
||||
}
|
||||
|
@ -44,6 +44,11 @@
|
||||
*
|
||||
* - copies mail-attributes from ldap to AD (example is from Mandriva mailAccount schema, need to adapt to other schema!)
|
||||
* (no_sid_check=1 uses all objectClass=posixAccount, not checking for having a SID and uid not ending in $ for computer accounts)
|
||||
*
|
||||
* setup/setup-cli.php [--dry-run] --setup_cmd_ldap <domain>,<config-user>,<config-pw> sub_command=passwords_to_sql \
|
||||
* ldap_base=dc=local ldap_root_dn=cn=admin,dc=local ldap_root_pw=secret ldap_host=localhost
|
||||
*
|
||||
* Updating passwords for existing users in SQL from LDAP, eg. to switch off authentication to LDAP on a SQL install.
|
||||
*/
|
||||
class setup_cmd_ldap extends setup_cmd
|
||||
{
|
||||
@ -63,19 +68,19 @@ class setup_cmd_ldap extends setup_cmd
|
||||
* Constructor
|
||||
*
|
||||
* @param string/array $domain domain-name to customize the defaults or array with all parameters
|
||||
* @param string $ldap_host=null
|
||||
* @param string $ldap_suffix=null base of the whole ldap install, default "dc=local"
|
||||
* @param string $ldap_admin=null root-dn needed to create new entries in the suffix
|
||||
* @param string $ldap_admin_pw=null
|
||||
* @param string $ldap_base=null base of the instance, default "o=$domain,$suffix"
|
||||
* @param string $ldap_root_dn=null root-dn used for the instance, default "cn=admin,$base"
|
||||
* @param string $ldap_root_pw=null
|
||||
* @param string $ldap_context=null ou for accounts, default "ou=accounts,$base"
|
||||
* @param string $ldap_search_filter=null search-filter for accounts, default "(uid=%user)"
|
||||
* @param string $ldap_group_context=null ou for groups, default "ou=groups,$base"
|
||||
* @param string $sub_command='create_ldap' 'create_ldap', 'test_ldap', 'test_ldap_root', see exec method
|
||||
* @param string $ldap_encryption_type='des'
|
||||
* @param boolean $truncate_egw_accounts=false truncate accounts table before migration to SQL
|
||||
* @param string $ldap_host =null
|
||||
* @param string $ldap_suffix =null base of the whole ldap install, default "dc=local"
|
||||
* @param string $ldap_admin =null root-dn needed to create new entries in the suffix
|
||||
* @param string $ldap_admin_pw =null
|
||||
* @param string $ldap_base =null base of the instance, default "o=$domain,$suffix"
|
||||
* @param string $ldap_root_dn =null root-dn used for the instance, default "cn=admin,$base"
|
||||
* @param string $ldap_root_pw =null
|
||||
* @param string $ldap_context =null ou for accounts, default "ou=accounts,$base"
|
||||
* @param string $ldap_search_filter =null search-filter for accounts, default "(uid=%user)"
|
||||
* @param string $ldap_group_context =null ou for groups, default "ou=groups,$base"
|
||||
* @param string $sub_command ='create_ldap' 'create_ldap', 'test_ldap', 'test_ldap_root', see exec method
|
||||
* @param string $ldap_encryption_type ='des'
|
||||
* @param boolean $truncate_egw_accounts =false truncate accounts table before migration to SQL
|
||||
*/
|
||||
function __construct($domain,$ldap_host=null,$ldap_suffix=null,$ldap_admin=null,$ldap_admin_pw=null,
|
||||
$ldap_base=null,$ldap_root_dn=null,$ldap_root_pw=null,$ldap_context=null,$ldap_search_filter=null,
|
||||
@ -107,7 +112,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
/**
|
||||
* run the command: test or create the ldap connection and hierarchy
|
||||
*
|
||||
* @param boolean $check_only=false only run the checks (and throw the exceptions), but not the command itself
|
||||
* @param boolean $check_only =false only run the checks (and throw the exceptions), but not the command itself
|
||||
* @return string success message
|
||||
* @throws Exception(lang('Wrong credentials to access the header.inc.php file!'),2);
|
||||
* @throws Exception('header.inc.php not found!');
|
||||
@ -141,7 +146,8 @@ class setup_cmd_ldap extends setup_cmd
|
||||
break;
|
||||
case 'migrate_to_ldap':
|
||||
case 'migrate_to_sql':
|
||||
$msg = $this->migrate($this->sub_command == 'migrate_to_ldap');
|
||||
case 'passwords_to_sql':
|
||||
$msg = $this->migrate($this->sub_command);
|
||||
break;
|
||||
case 'set_mailbox':
|
||||
$msg = $this->set_mailbox($check_only);
|
||||
@ -169,7 +175,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
* Then run admin/admin-cli.php --change-account-id and after this command again without --dry-run.
|
||||
* After that you need to run the given chown.php command to change filesystem uid/gid in samba share.
|
||||
*
|
||||
* @param boolean $check_only=false true: only connect and output necessary commands
|
||||
* @param boolean $check_only =false true: only connect and output necessary commands
|
||||
*/
|
||||
private function sid2uidnumber($check_only=false)
|
||||
{
|
||||
@ -254,7 +260,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
/**
|
||||
* Copy given attributes of accounts of one ldap to active directory
|
||||
*
|
||||
* @param boolean $check_only=false true: only connect and output necessary commands
|
||||
* @param boolean $check_only =false true: only connect and output necessary commands
|
||||
*/
|
||||
private function copy2ad($check_only=false)
|
||||
{
|
||||
@ -326,13 +332,14 @@ class setup_cmd_ldap extends setup_cmd
|
||||
throw new egw_exception(lang('Error searching "dn=%1" for "%2"!',$this->ldap_base, $search));
|
||||
}
|
||||
$changed = 0;
|
||||
$utc_diff = null;
|
||||
foreach($entries as $key => $entry)
|
||||
{
|
||||
if ($key === 'count') continue;
|
||||
|
||||
$entry = ldap::result2array($entry);
|
||||
$uid = $entry['uid'];
|
||||
$entry = array_diff_key($entry, $ignore_attr);
|
||||
$entry_arr = ldap::result2array($entry);
|
||||
$uid = $entry_arr['uid'];
|
||||
$entry = array_diff_key($entry_arr, $ignore_attr);
|
||||
|
||||
if (!($sr = ldap_search($ads->ds, $this->ads_context,
|
||||
$search='(&(objectClass=user)(sAMAccountName='.ldap::quote($uid).'))', array('dn'))) ||
|
||||
@ -354,8 +361,8 @@ class setup_cmd_ldap extends setup_cmd
|
||||
else
|
||||
{
|
||||
if (is_null($utc_diff)) $utc_diff = date('Z');
|
||||
$entry['shadowexpire'] = $value*24*3600+$utc_diff; // ldap time to unixTime
|
||||
$entry['shadowexpire'] = accounts_ads::convertUnixTimeToWindowsTime($entry['shadowexpire']);
|
||||
$entry['shadowexpire'] = accounts_ads::convertUnixTimeToWindowsTime(
|
||||
$entry['shadowexpire']*24*3600+$utc_diff); // ldap time to unixTime
|
||||
}
|
||||
}
|
||||
$update = array();
|
||||
@ -364,7 +371,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
if ($value || $attr === '')
|
||||
{
|
||||
$to = isset($rename[$attr]) ? $rename[$attr] : $attr;
|
||||
unset($prefix);
|
||||
$prefix = null;
|
||||
if ($to[0] == '{') // eg. {smtp:}proxyAddresses=forwardTo
|
||||
{
|
||||
list($prefix, $to) = explode('}', substr($to, 1));
|
||||
@ -414,12 +421,15 @@ class setup_cmd_ldap extends setup_cmd
|
||||
/**
|
||||
* Migrate to other account storage
|
||||
*
|
||||
* @param boolean $to_ldap true: sql --> ldap, false: ldap --> sql
|
||||
* @param boolean|string $to_ldap true: sql --> ldap, false: ldap --> sql, "passwords_to_sql", "migrate_to_(sql|ldap)"
|
||||
* @return string with success message
|
||||
* @throws Exception on error
|
||||
*/
|
||||
private function migrate($to_ldap)
|
||||
{
|
||||
$passwords2sql = $to_ldap === "passwords_to_sql";
|
||||
if (is_string($to_ldap)) $to_ldap = substr($to_ldap, -8) == '_to_ldap';
|
||||
|
||||
$msg = array();
|
||||
// if migrating to ldap, check ldap and create context if not yet exiting
|
||||
if ($to_ldap && !empty($this->ldap_admin_pw))
|
||||
@ -431,7 +441,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
$msg[] = $this->connect();
|
||||
}
|
||||
// read accounts from old store
|
||||
$accounts = $this->accounts(!$to_ldap);
|
||||
$accounts = $this->accounts(!$to_ldap, $passwords2sql ? 'accounts' : 'both');
|
||||
|
||||
// clean up SQL before migration
|
||||
if (!$to_ldap && $this->truncate_egw_accounts)
|
||||
@ -442,7 +452,8 @@ class setup_cmd_ldap extends setup_cmd
|
||||
// instanciate accounts obj for new store
|
||||
$accounts_obj = $this->accounts_obj($to_ldap);
|
||||
|
||||
$accounts_created = $groups_created = $errors = 0;
|
||||
$accounts_created = $groups_created = $errors = $egw_info_set = 0;
|
||||
$emailadmin_src = $ldap_class = null;
|
||||
$target = $to_ldap ? 'LDAP' : 'SQL';
|
||||
foreach($accounts as $account_id => $account)
|
||||
{
|
||||
@ -456,6 +467,31 @@ class setup_cmd_ldap extends setup_cmd
|
||||
// invalidate cache: otherwise no migration takes place, if cached results says account already exists
|
||||
accounts::cache_invalidate($account_id);
|
||||
|
||||
if ($passwords2sql)
|
||||
{
|
||||
if (!($sql_account = $accounts_obj->read($account_id)))
|
||||
{
|
||||
$msg[] = lang('%1 does NOT exist in %2.',$what,$target);
|
||||
$errors++;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql_account['account_passwd'] = self::hash_ldap2sql($account['account_pwd']);
|
||||
|
||||
if (!$accounts_obj->save($sql_account))
|
||||
{
|
||||
$msg[] = lang('Update of %1 in %2 failed !!!',$what,$target);
|
||||
$errors++;
|
||||
}
|
||||
else
|
||||
{
|
||||
$msg[] = lang('%1 password set in %2.',$what,$target);
|
||||
$accounts_created++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($account['account_type'] == 'u')
|
||||
{
|
||||
if ($accounts_obj->exists($account_id))
|
||||
@ -601,6 +637,11 @@ class setup_cmd_ldap extends setup_cmd
|
||||
$accounts_obj->set_members($account['members'],$account_id);
|
||||
}
|
||||
}
|
||||
if ($passwords2sql)
|
||||
{
|
||||
return lang('%1 passwords updated, %3 errors',$accounts_created,$groups_created,$errors).
|
||||
($errors || $this->verbose ? "\n- ".implode("\n- ",$msg) : '');
|
||||
}
|
||||
// migrate addressbook data
|
||||
$GLOBALS['egw_info']['user']['apps']['admin'] = true; // otherwise migration will not run in setup!
|
||||
$addressbook = new addressbook_so();
|
||||
@ -613,12 +654,12 @@ class setup_cmd_ldap extends setup_cmd
|
||||
}
|
||||
ob_start();
|
||||
$addressbook->migrate2ldap($to_ldap ? 'accounts' : 'accounts-back');
|
||||
$msg = array_merge($msg, explode("\n", strip_tags(ob_get_clean())));
|
||||
$msgs = array_merge($msg, explode("\n", strip_tags(ob_get_clean())));
|
||||
|
||||
$this->restore_db();
|
||||
|
||||
return lang('%1 users and %2 groups created, %3 errors',$accounts_created,$groups_created,$errors).
|
||||
($errors || $this->verbose ? "\n- ".implode("\n- ",$msg) : '');
|
||||
($errors || $this->verbose ? "\n- ".implode("\n- ",$msgs) : '');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -631,6 +672,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
{
|
||||
if (!($type = $GLOBALS['egw_info']['server']['sql_encryption_type'])) $type = 'md5';
|
||||
|
||||
$matches = null;
|
||||
if (preg_match('/^\\{(.*)\\}(.*)$/',$hash,$matches))
|
||||
{
|
||||
list(,$type,$hash) = $matches;
|
||||
@ -672,15 +714,16 @@ class setup_cmd_ldap extends setup_cmd
|
||||
/**
|
||||
* Read all accounts from sql or ldap
|
||||
*
|
||||
* @param boolean $from_ldap=true true: ldap, false: sql
|
||||
* @param boolean $from_ldap =true true: ldap, false: sql
|
||||
* @param string $type ='both'
|
||||
* @return array
|
||||
*/
|
||||
public function accounts($from_ldap=true)
|
||||
public function accounts($from_ldap=true, $type='both')
|
||||
{
|
||||
$accounts_obj = $this->accounts_obj($from_ldap);
|
||||
//error_log(__METHOD__."(from_ldap=".array2string($from_ldap).') get_class(accounts_obj->backend)='.get_class($accounts_obj->backend));
|
||||
|
||||
$accounts = $accounts_obj->search(array('type' => 'both', 'objectclass' => true));
|
||||
$accounts = $accounts_obj->search(array('type' => $type, 'objectclass' => true));
|
||||
|
||||
foreach($accounts as $account_id => &$account)
|
||||
{
|
||||
@ -713,7 +756,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
*/
|
||||
private function accounts_obj($ldap)
|
||||
{
|
||||
static $enviroment_setup;
|
||||
static $enviroment_setup=null;
|
||||
if (!$enviroment_setup)
|
||||
{
|
||||
parent::_setup_enviroment($this->domain);
|
||||
@ -739,9 +782,9 @@ class setup_cmd_ldap extends setup_cmd
|
||||
/**
|
||||
* Connect to ldap server
|
||||
*
|
||||
* @param string $dn=null default $this->ldap_root_dn
|
||||
* @param string $pw=null default $this->ldap_root_pw
|
||||
* @param string $host=null default $this->ldap_host, hostname, ip or ldap-url
|
||||
* @param string $dn =null default $this->ldap_root_dn
|
||||
* @param string $pw =null default $this->ldap_root_pw
|
||||
* @param string $host =null default $this->ldap_host, hostname, ip or ldap-url
|
||||
* @throws egw_exception_wrong_userinput Can not connect to ldap ...
|
||||
*/
|
||||
private function connect($dn=null,$pw=null,$host=null)
|
||||
@ -813,7 +856,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
$this->ldap_root_dn => array('userPassword' => auth::encrypt_ldap($this->ldap_root_pw,'ssha')),
|
||||
) as $dn => $extra)
|
||||
{
|
||||
if (!$this->_create_node($dn,$extra,$check_only) && $dn == $this->ldap_root_dn)
|
||||
if (!$this->_create_node($dn,$extra,$this->check_only) && $dn == $this->ldap_root_dn)
|
||||
{
|
||||
// ldap_root already existed, lets check the pw is correct
|
||||
$this->connect();
|
||||
@ -884,9 +927,9 @@ class setup_cmd_ldap extends setup_cmd
|
||||
*
|
||||
* Uses $this->ldap_host, $this->ldap_admin and $this->ldap_admin_pw to connect.
|
||||
*
|
||||
* @param string $this->object_class='qmailUser'
|
||||
* @param string $this->mbox_attr='mailmessagestore' lowercase!!!
|
||||
* @param string $this->mail_login_type='email' 'email', 'vmailmgr', 'standard' or 'uidNumber'
|
||||
* @param string $this->object_class ='qmailUser'
|
||||
* @param string $this->mbox_attr ='mailmessagestore' lowercase!!!
|
||||
* @param string $this->mail_login_type ='email' 'email', 'vmailmgr', 'standard' or 'uidNumber'
|
||||
* @return string with success message N entries modified
|
||||
* @throws egw_exception if dn not found, not listable or delete fails
|
||||
*/
|
||||
@ -931,7 +974,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
$mbox_attr => $mbox,
|
||||
)))
|
||||
{
|
||||
throw new egw_exception(lang("Error modifying dn=%1: %2='%3'!",$dn,$mbox_attr,$mbox));
|
||||
throw new egw_exception(lang("Error modifying dn=%1: %2='%3'!",$entry['dn'],$mbox_attr,$mbox));
|
||||
}
|
||||
++$modified;
|
||||
if ($check_only) echo "$modified: $entry[dn]: $mbox_attr={$entry[$mbox_attr][0]} --> $mbox\n";
|
||||
@ -957,7 +1000,7 @@ class setup_cmd_ldap extends setup_cmd
|
||||
* Create a new node in the ldap tree
|
||||
*
|
||||
* @param string $dn dn to create, eg. "cn=admin,dc=local"
|
||||
* @param array $extra=array() extra attributes to set
|
||||
* @param array $extra =array() extra attributes to set
|
||||
* @return boolean true if the node was create, false if it was already there
|
||||
* @throws egw_exception_wrong_userinput
|
||||
*/
|
||||
|
@ -54,6 +54,7 @@
|
||||
<tr bgcolor="#e6e6e6">
|
||||
<td colspan="2" align="center">
|
||||
<input type="submit" name="migrate" value="{migrate}" />
|
||||
{extra_button}
|
||||
<input type="submit" name="cancel" value="{cancel}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
Loading…
Reference in New Issue
Block a user