parent
652caa1c88
commit
53db1fe5ac
@ -0,0 +1,83 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud - user_ldap |
||||
* |
||||
* @author Arthur Schiwon |
||||
* @copyright 2013 Arthur Schiwon blizzz@owncloud.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
// Check user and app status |
||||
OCP\JSON::checkAdminUser(); |
||||
OCP\JSON::checkAppEnabled('user_ldap'); |
||||
OCP\JSON::callCheck(); |
||||
|
||||
$l=OC_L10N::get('user_ldap'); |
||||
|
||||
if(!isset($_POST['action'])) { |
||||
\OCP\JSON::error(array('message' => $l->t('No action specified'))); |
||||
} |
||||
$action = $_POST['action']; |
||||
|
||||
|
||||
if(!isset($_POST['ldap_serverconfig_chooser'])) { |
||||
\OCP\JSON::error(array('message' => $l->t('No configuration specified'))); |
||||
} |
||||
$prefix = $_POST['ldap_serverconfig_chooser']; |
||||
|
||||
$ldapWrapper = new OCA\user_ldap\lib\LDAP(); |
||||
$configuration = new \OCA\user_ldap\lib\Configuration($prefix); |
||||
$wizard = new \OCA\user_ldap\lib\Wizard($configuration, $ldapWrapper); |
||||
|
||||
switch($action) { |
||||
case 'guessPortAndTLS': |
||||
try { |
||||
$result = $wizard->$action(); |
||||
if($result !== false) { |
||||
OCP\JSON::success($result->getResultArray()); |
||||
exit; |
||||
} |
||||
} catch (\Exception $e) { |
||||
\OCP\JSON::error(array('message' => $e->getMessage())); |
||||
exit; |
||||
} |
||||
\OCP\JSON::error(); |
||||
exit; |
||||
break; |
||||
|
||||
case 'save': |
||||
$key = isset($_POST['cfgkey']) ? $_POST['cfgkey'] : false; |
||||
$val = isset($_POST['cfgval']) ? $_POST['cfgval'] : null; |
||||
if($key === false || is_null($val)) { |
||||
\OCP\JSON::error(array('message' => $l->t('No data specified'))); |
||||
exit; |
||||
} |
||||
$cfg = array($key => $val); |
||||
$setParameters = array(); |
||||
$configuration->setConfiguration($cfg, $setParameters); |
||||
if(!in_array($key, $setParameters)) { |
||||
\OCP\JSON::error(array('message' => $l->t($key.' Could not set configuration '.$setParameters[0]))); |
||||
exit; |
||||
} |
||||
$configuration->saveConfiguration(); |
||||
OCP\JSON::success(); |
||||
break; |
||||
default: |
||||
//TODO: return 4xx error |
||||
break; |
||||
} |
||||
|
||||
@ -0,0 +1,267 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud – LDAP Wizard |
||||
* |
||||
* @author Arthur Schiwon |
||||
* @copyright 2013 Arthur Schiwon blizzz@owncloud.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\user_ldap\lib; |
||||
|
||||
class Wizard extends LDAPUtility { |
||||
static protected $l; |
||||
protected $configuration; |
||||
protected $result; |
||||
|
||||
/** |
||||
* @brief Constructor |
||||
* @param $configuration an instance of Configuration |
||||
* @param $ldap an instance of ILDAPWrapper |
||||
*/ |
||||
public function __construct(Configuration $configuration, ILDAPWrapper $ldap) { |
||||
parent::__construct($ldap); |
||||
$this->configuration = $configuration; |
||||
if(is_null(Wizard::$l)) { |
||||
Wizard::$l = \OC_L10N::get('user_ldap'); |
||||
} |
||||
$this->result = new WizardResult; |
||||
} |
||||
|
||||
public function __destruct() { |
||||
if($this->result->hasChanges()) { |
||||
$this->configuration->saveConfiguration(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Tries to determine the port, requires given Host, User DN and Password |
||||
* @returns mixed WizardResult on success, false otherwise |
||||
*/ |
||||
public function guessPortAndTLS() { |
||||
if(!$this->checkRequirements(array('ldapHost', |
||||
'ldapAgentName', |
||||
'ldapAgentPassword'))) { |
||||
return false; |
||||
} |
||||
$this->checkHost(); |
||||
$portSettings = $this->getPortSettingsToTry(); |
||||
file_put_contents('/tmp/ps', print_r($portSettings, true).PHP_EOL, FILE_APPEND); |
||||
|
||||
if(!is_array($portSettings)) { |
||||
throw new \Exception(print_r($portSettings, true)); |
||||
} |
||||
|
||||
//proceed from the best configuration and return on first success |
||||
foreach($portSettings as $setting) { |
||||
$p = $setting['port']; |
||||
$t = $setting['tls']; |
||||
\OCP\Util::writeLog('user_ldap', 'Wiz: trying port '. $p . ', TLS '. $t, \OCP\Util::DEBUG); |
||||
//connectAndBind may throw Exception, it needs to be catched by the |
||||
//callee of this method |
||||
if($this->connectAndBind($p, $t) === true) { |
||||
$config = array('ldapPort' => $p, |
||||
'ldapTLS' => intval($t) |
||||
); |
||||
$this->configuration->setConfiguration($config); |
||||
\OCP\Util::writeLog('user_ldap', 'Wiz: detected Port '. $p, \OCP\Util::DEBUG); |
||||
$this->result->addChange('ldap_port', $p); |
||||
$this->result->addChange('ldap_tls', intval($t)); |
||||
// $this->result->addSpecific('port', $p); |
||||
return $this->result; |
||||
} |
||||
} |
||||
|
||||
//custom port, undetected (we do not brute force) |
||||
return false; |
||||
} |
||||
|
||||
public function guessBaseDN() { |
||||
if(!$this->checkRequirements(array('ldapHost', |
||||
'ldapAgentName', |
||||
'ldapAgentPassword', |
||||
'ldapPort', |
||||
))) { |
||||
return false; |
||||
} |
||||
$cr = $this->getConnection(); |
||||
if(!$cr) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @brief Checks, whether a port was entered in the Host configuration |
||||
* field. In this case the port will be stripped off, but also stored as |
||||
* setting. |
||||
*/ |
||||
private function checkHost() { |
||||
$host = $this->configuration->ldapHost; |
||||
$hostInfo = parse_url($host); |
||||
|
||||
//removes Port from Host |
||||
if(is_array($hostInfo) && isset($hostInfo['port'])) { |
||||
$port = $hostInfo['port']; |
||||
$host = str_replace(':'.$port, '', $host); |
||||
$config = array('ldapHost' => $host, |
||||
'ldapPort' => $port, |
||||
); |
||||
$this->result->addChange('ldap_host', $host); |
||||
$this->result->addChange('ldap_port', $port); |
||||
$this->configuration->setConfiguration($config); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Connects and Binds to an LDAP Server |
||||
* @param $port the port to connect with |
||||
* @param $tls whether startTLS is to be used |
||||
* @return |
||||
*/ |
||||
private function connectAndBind($port = 389, $tls = false, $ncc = false) { |
||||
if($ncc) { |
||||
//No certificate check |
||||
//FIXME: undo afterwards |
||||
putenv('LDAPTLS_REQCERT=never'); |
||||
} |
||||
|
||||
//connect, does not really trigger any server communication |
||||
\OCP\Util::writeLog('user_ldap', 'Wiz: Checking Host Info ', \OCP\Util::DEBUG); |
||||
$host = $this->configuration->ldapHost; |
||||
$hostInfo = parse_url($host); |
||||
if(!$hostInfo) { |
||||
throw new \Exception($this->l->t('Invalid Host')); |
||||
} |
||||
if(isset($hostInfo['scheme'])) { |
||||
if(isset($hostInfo['port'])) { |
||||
//problem |
||||
} else { |
||||
$host .= ':' . $port; |
||||
} |
||||
} |
||||
\OCP\Util::writeLog('user_ldap', 'Wiz: Attempting to connect ', \OCP\Util::DEBUG); |
||||
$cr = $this->ldap->connect($host, $port); |
||||
if(!is_resource($cr)) { |
||||
throw new \Exception($this->l->t('Invalid Host')); |
||||
} |
||||
|
||||
\OCP\Util::writeLog('user_ldap', 'Wiz: Setting LDAP Options ', \OCP\Util::DEBUG); |
||||
//set LDAP options |
||||
if($this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3)) { |
||||
if($tls) { |
||||
$this->ldap->startTls($cr); |
||||
} |
||||
} |
||||
|
||||
\OCP\Util::writeLog('user_ldap', 'Wiz: Attemping to Bind ', \OCP\Util::DEBUG); |
||||
//interesting part: do the bind! |
||||
$login = $this->ldap->bind($cr, |
||||
$this->configuration->ldapAgentName, |
||||
$this->configuration->ldapAgentPassword); |
||||
|
||||
if($login === true) { |
||||
$this->ldap->unbind($cr); |
||||
if($ncc) { |
||||
throw new \Exception('Certificate cannot be validated.'); |
||||
} |
||||
\OCP\Util::writeLog('user_ldap', 'Wiz: Bind succesfull with Port '. $port, \OCP\Util::DEBUG); |
||||
return true; |
||||
} |
||||
|
||||
$errno = $this->ldap->errno($cr); |
||||
$error = ldap_error($cr); |
||||
$this->ldap->unbind($cr); |
||||
if($errno === -1 || ($errno === 2 && $ncc)) { |
||||
//host, port or TLS wrong |
||||
return false; |
||||
} else if ($errno === 2) { |
||||
return $this->connectAndBind($port, $tls, true); |
||||
} |
||||
throw new \Exception($error); |
||||
} |
||||
|
||||
private function checkRequirements($reqs) { |
||||
foreach($reqs as $option) { |
||||
$value = $this->configuration->$option; |
||||
if(empty($value)) { |
||||
return false; |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
private function getConnection() { |
||||
$cr = $this->ldap->connect( |
||||
$this->configuration->ldapHost.':'.$this->configuration->ldapPort, |
||||
$this->configuration->ldapPort); |
||||
|
||||
if($this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3)) { |
||||
if($this->configuration->ldapTLS === 1) { |
||||
$this->ldap->startTls($cr); |
||||
} |
||||
} |
||||
|
||||
$lo = @$this->ldap->bind($cr, |
||||
$this->configuration->ldapAgentName, |
||||
$this->configuration->ldapAgentPassword); |
||||
if($lo === true) { |
||||
return $cr; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
private function getDefaultLdapPortSettings() { |
||||
static $settings = array( |
||||
array('port' => 7636, 'tls' => false), |
||||
array('port' => 636, 'tls' => false), |
||||
array('port' => 7389, 'tls' => true), |
||||
array('port' => 389, 'tls' => true), |
||||
array('port' => 7389, 'tls' => false), |
||||
array('port' => 389, 'tls' => false), |
||||
); |
||||
return $settings; |
||||
} |
||||
|
||||
private function getPortSettingsToTry() { |
||||
//389 ← LDAP / Unencrypted or StartTLS |
||||
//636 ← LDAPS / SSL |
||||
//7xxx ← UCS. need to be checked first, because both ports may be open |
||||
$host = $this->configuration->ldapHost; |
||||
$port = intval($this->configuration->ldapPort); |
||||
$portSettings = array(); |
||||
|
||||
//In case the port is already provided, we will check this first |
||||
if($port > 0) { |
||||
$hostInfo = parse_url($host); |
||||
if(is_array($hostInfo) |
||||
&& isset($hostInfo['scheme']) |
||||
&& stripos($hostInfo['scheme'], 'ldaps') === false) { |
||||
$portSettings[] = array('port' => $port, 'tls' => true); |
||||
} |
||||
$portSettings[] =array('port' => $port, 'tls' => false); |
||||
} |
||||
|
||||
//default ports |
||||
$portSettings = array_merge($portSettings, |
||||
$this->getDefaultLdapPortSettings()); |
||||
|
||||
return $portSettings; |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,50 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* ownCloud – LDAP Wizard Result |
||||
* |
||||
* @author Arthur Schiwon |
||||
* @copyright 2013 Arthur Schiwon blizzz@owncloud.com |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCA\user_ldap\lib; |
||||
|
||||
class WizardResult { |
||||
protected $changes = array(); |
||||
protected $specifics = array(); |
||||
|
||||
public function addChange($key, $value) { |
||||
$this->changes[$key] = $value; |
||||
} |
||||
|
||||
public function hasChanges() { |
||||
return count($this->changes) > 0; |
||||
} |
||||
|
||||
public function addSpecific($key, $value) { |
||||
$this->specifics[$key] = $value; |
||||
} |
||||
|
||||
public function getResultArray() { |
||||
$result = array(); |
||||
$result['changes'] = $this->changes; |
||||
foreach($this->specifics as $key => $value) { |
||||
$result[$key] = $value; |
||||
} |
||||
return $result; |
||||
} |
||||
} |
||||
@ -0,0 +1,12 @@ |
||||
<div class="ldapSettingControls"> |
||||
<input id="ldap_submit" type="submit" value="Save" /> |
||||
<button id="ldap_action_test_connection" name="ldap_action_test_connection"> |
||||
<?php p($l->t('Test Configuration'));?> |
||||
</button> |
||||
<a href="<?php p($theme->getDocBaseUrl()); ?>/server/5.0/admin_manual/auth_ldap.html"
|
||||
target="_blank"> |
||||
<img src="<?php print_unescaped(OCP\Util::imagePath('', 'actions/info.png')); ?>"
|
||||
style="height:1.75ex" /> |
||||
<?php p($l->t('Help'));?> |
||||
</a> |
||||
</div> |
||||
@ -0,0 +1,76 @@ |
||||
<fieldset id="ldapWizard1"> |
||||
<p> |
||||
<select id="ldap_serverconfig_chooser" name="ldap_serverconfig_chooser"> |
||||
<?php if(count($_['serverConfigurationPrefixes']) === 0 ) { |
||||
?> |
||||
<option value="" selected>1. Server</option>'); |
||||
<?php |
||||
} else { |
||||
$i = 1; |
||||
$sel = ' selected'; |
||||
foreach($_['serverConfigurationPrefixes'] as $prefix) { |
||||
?> |
||||
<option value="<?php p($prefix); ?>"<?php p($sel); $sel = ''; ?>><?php p($i++); ?>. Server: <?php p($_['serverConfigurationHosts'][$prefix]); ?></option>
|
||||
<?php |
||||
} |
||||
} |
||||
?> |
||||
<option value="NEW"><?php p($l->t('Add Server Configuration'));?></option>
|
||||
</select> |
||||
<button id="ldap_action_delete_configuration" |
||||
name="ldap_action_delete_configuration">Delete Configuration</button> |
||||
</p> |
||||
|
||||
<div class="hostPortCombinator"> |
||||
<div class="tablerow"> |
||||
<div class="tablecell"> |
||||
<div class="table"> |
||||
<input type="text" class="host tablecell lwautosave" id="ldap_host" |
||||
name="ldap_host" |
||||
data-default="<?php p($_['ldap_host_default']); ?>"
|
||||
placeholder="<?php p($l->t('Host'));?>"
|
||||
title="<?php p($l->t('You can omit the protocol, except you require SSL. Then start with ldaps://'));?>"
|
||||
/> |
||||
<span> |
||||
<input type="number" id="ldap_port" name="ldap_port" |
||||
class="hidden lwautosave" |
||||
data-default="<?php p($_['ldap_port_default']); ?>"
|
||||
placeholder="<?php p($l->t('Port'));?>" />
|
||||
</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="tablerow"> |
||||
<input type="text" id="ldap_dn" name="ldap_dn" |
||||
class="tablecell lwautosave" |
||||
data-default="<?php p($_['ldap_dn_default']); ?>"
|
||||
placeholder="<?php p($l->t('User DN'));?>"
|
||||
title="<?php p($l->t('The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty.'));?>"
|
||||
/> |
||||
</div> |
||||
|
||||
<div class="tablerow"> |
||||
<input type="password" id="ldap_agent_password" |
||||
class="tablecell lwautosave" name="ldap_agent_password" |
||||
data-default="<?php p($_['ldap_agent_password_default']); ?>"
|
||||
placeholder="<?php p($l->t('Password'));?>"
|
||||
title="<?php p($l->t('For anonymous access, leave DN and Password empty.'));?>"
|
||||
/> |
||||
</div> |
||||
|
||||
<div class="tablerow"> |
||||
<textarea id="ldap_base" name="ldap_base" |
||||
class="tablecell hidden lwautosave" |
||||
placeholder="<?php p($l->t('One Base DN per line'));?>"
|
||||
title="<?php p($l->t('You can specify Base DN for users and groups in the Advanced tab'));?>"
|
||||
data-default="<?php p($_['ldap_base_default']); ?>" >
|
||||
</textarea> |
||||
</div> |
||||
|
||||
<div class="tablerow"> |
||||
<div class="tablecell ldapWizardInfo hidden"> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<?php print_unescaped($_['wizardControls']); ?> |
||||
</fieldset> |
||||
@ -0,0 +1,14 @@ |
||||
<div class="ldapWizardControls"> |
||||
<button id="ldap_action_back" name="ldap_action_back" class="hidden"> |
||||
<?php p($l->t('Back'));?> |
||||
</button> |
||||
<button id="ldap_action_continue" name="ldap_action_continue"> |
||||
<?php p($l->t('Continue'));?> |
||||
</button> |
||||
<a href="<?php p($theme->getDocBaseUrl()); ?>/server/5.0/admin_manual/auth_ldap.html"
|
||||
target="_blank"> |
||||
<img src="<?php print_unescaped(OCP\Util::imagePath('', 'actions/info.png')); ?>"
|
||||
style="height:1.75ex" /> |
||||
<?php p($l->t('Help'));?> |
||||
</a> |
||||
</div> |
||||
Loading…
Reference in new issue