SF Feature #2073323 - Using Single Sign On authentication
This commit is contained in:
parent
ed4784b1b6
commit
57d405fe3b
@ -21,6 +21,8 @@ access to dn.regex="o=Simpsons$"
|
||||
access to *
|
||||
by * read
|
||||
|
||||
authz-policy any
|
||||
|
||||
database bdb
|
||||
suffix "dc=example.com"
|
||||
rootdn "cn=Manager,dc=example.com"
|
||||
|
@ -128,6 +128,10 @@ class HTMLTree extends Tree {
|
||||
$this->draw_login_link();
|
||||
break;
|
||||
|
||||
case 'config':
|
||||
case 'proxy':
|
||||
break;
|
||||
|
||||
default:
|
||||
die(sprintf('Error: %s hasnt been configured for auth_type %s',__METHOD__,$server->getAuthType()));
|
||||
}
|
||||
@ -294,7 +298,7 @@ class HTMLTree extends Tree {
|
||||
break;
|
||||
|
||||
case 'logout':
|
||||
if (in_array($server->getAuthType(),array('config','http')))
|
||||
if (in_array($server->getAuthType(),array('config','http','proxy')))
|
||||
return '';
|
||||
|
||||
$href = sprintf('cmd.php?cmd=logout&server_id=%s',$server->getIndex());
|
||||
@ -514,17 +518,6 @@ class HTMLTree extends Tree {
|
||||
$this->getDepth()+3-1,_('(Session timed out. Automatically logged out.)'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw out link
|
||||
*/
|
||||
protected function draw_logout_link() {
|
||||
$server = $this->getServer();
|
||||
|
||||
if (! in_array($server->getAuthType(),array('config','http')))
|
||||
printf('<tr><td class="spacer"></td><td colspan="%s"><small><a href="cmd.php?cmd=%s&server_id=%s">%s</a></small></td></tr>',
|
||||
$this->getDepth()+3-1,get_custom_file($server->getIndex(),'logout',''),$server->getIndex(),_('logout'));
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is javascript, draw it
|
||||
*/
|
||||
|
38
lib/ds.php
38
lib/ds.php
@ -128,6 +128,7 @@ abstract class DS {
|
||||
switch ($this->getValue('login','auth_type')) {
|
||||
case 'config':
|
||||
case 'http':
|
||||
case 'proxy':
|
||||
case 'session':
|
||||
return $this->getValue('login','auth_type');
|
||||
|
||||
@ -145,7 +146,7 @@ abstract class DS {
|
||||
public function getLogin($method=null) {
|
||||
$method = $this->getMethod($method);
|
||||
|
||||
if ($method == 'unauth')
|
||||
if ($method == 'anon')
|
||||
return '';
|
||||
|
||||
switch ($this->getAuthType()) {
|
||||
@ -155,6 +156,12 @@ abstract class DS {
|
||||
else
|
||||
return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['name']);
|
||||
|
||||
case 'proxy':
|
||||
if (! isset($_SESSION['USER'][$this->index][$method]['proxy']))
|
||||
return $this->getValue('login','bind_id');
|
||||
else
|
||||
return blowfish_decrypt($_SESSION['USER'][$this->index][$method]['proxy']);
|
||||
|
||||
case 'http':
|
||||
case 'session':
|
||||
if (! isset($_SESSION['USER'][$this->index][$method]['name']))
|
||||
@ -175,6 +182,12 @@ abstract class DS {
|
||||
|
||||
switch ($this->getAuthType()) {
|
||||
case 'config':
|
||||
return true;
|
||||
|
||||
case 'proxy':
|
||||
if (isset($_SESSION['USER'][$this->index][$method]['proxy']))
|
||||
unset($_SESSION['USER'][$this->index][$method]['proxy']);
|
||||
|
||||
case 'http':
|
||||
case 'session':
|
||||
$_SESSION['USER'][$this->index][$method]['name'] = blowfish_encrypt($user);
|
||||
@ -193,11 +206,12 @@ abstract class DS {
|
||||
protected function getPassword($method=null) {
|
||||
$method = $this->getMethod($method);
|
||||
|
||||
if ($method == 'unauth')
|
||||
if ($method == 'anon')
|
||||
return '';
|
||||
|
||||
switch ($this->getAuthType()) {
|
||||
case 'config':
|
||||
case 'proxy':
|
||||
if (! isset($_SESSION['USER'][$this->index][$method]['pass']))
|
||||
return $this->getValue('login','bind_pass');
|
||||
else
|
||||
@ -230,6 +244,15 @@ abstract class DS {
|
||||
|
||||
# For some authentication types, we need to do the login here
|
||||
switch ($this->getAuthType()) {
|
||||
case 'config':
|
||||
if (! $CACHE[$this->index] = $this->login($this->getLogin($method),$this->getPassword($method),$method))
|
||||
system_message(array(
|
||||
'title'=>_('Unable to login.'),
|
||||
'body'=>_('Your configuration file has authentication set to CONFIG based authentication, however, the userid/password failed to login'),
|
||||
'type'=>'error'));
|
||||
|
||||
break;
|
||||
|
||||
case 'http':
|
||||
# If our auth vars are not set, throw up a login box.
|
||||
if (! isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
@ -272,6 +295,11 @@ abstract class DS {
|
||||
|
||||
break;
|
||||
|
||||
case 'proxy':
|
||||
$CACHE[$this->index] = $this->login($this->getValue('login','bind_id'),$this->getValue('login','bind_pass'),$method);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$CACHE[$this->index] = is_null($this->getLogin($method)) ? false : true;
|
||||
}
|
||||
@ -287,14 +315,10 @@ abstract class DS {
|
||||
|
||||
switch ($this->getAuthType()) {
|
||||
case 'config':
|
||||
if (isset($_SESSION['USER'][$this->index][$method]))
|
||||
unset($_SESSION['USER'][$this->index][$method]);
|
||||
|
||||
return true;
|
||||
|
||||
case 'http':
|
||||
return true;
|
||||
|
||||
case 'proxy':
|
||||
case 'session':
|
||||
if (isset($_SESSION['USER'][$this->index][$method]))
|
||||
unset($_SESSION['USER'][$this->index][$method]);
|
||||
|
131
lib/ds_ldap.php
131
lib/ds_ldap.php
@ -79,6 +79,10 @@ class ldap extends DS {
|
||||
'desc'=>'Limit logins to users who match any of the following LDAP filters',
|
||||
'default'=>array());
|
||||
|
||||
$this->default->proxy['attr'] = array(
|
||||
'desc'=>'Attribute to use to find the users DN for proxy based authentication',
|
||||
'default'=>array());
|
||||
|
||||
# SASL configuration
|
||||
$this->default->server['sasl'] = array(
|
||||
'desc'=>'Use SASL authentication when binding LDAP server',
|
||||
@ -209,15 +213,24 @@ class ldap extends DS {
|
||||
debug_log('Leaving with FALSE, bind FAILed',16,__FILE__,__LINE__,__METHOD__);
|
||||
|
||||
$this->noconnect = true;
|
||||
$CACHE[$this->index][$method] = null;
|
||||
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s %s',_('Unable to connect to LDAP server'),$this->getName()),
|
||||
'body'=>sprintf('<b>%s</b>: %s (%s) for <b>%s</b>',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
|
||||
'type'=>'error'));
|
||||
|
||||
} else
|
||||
} else {
|
||||
$this->noconnect = false;
|
||||
|
||||
# If this is a proxy session, we need to switch to the proxy user
|
||||
if ($this->isProxyEnabled() && $bind['id'] && $method != 'anon')
|
||||
if (! $this->startProxy($resource,$method)) {
|
||||
$this->noconnect = true;
|
||||
$CACHE[$this->index][$method] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('run_hook'))
|
||||
run_hook('post_connect',array('server_id'=>$this->index,'method'=>$method,'id'=>$bind['id']));
|
||||
|
||||
@ -243,7 +256,7 @@ class ldap extends DS {
|
||||
if ($this->getValue('login','attr') == 'dn')
|
||||
$userDN = $user;
|
||||
else
|
||||
$userDN = $this->getLoginID($user,'unauth');
|
||||
$userDN = $this->getLoginID($user,'anon');
|
||||
|
||||
if (! $userDN)
|
||||
return false;
|
||||
@ -596,6 +609,106 @@ class ldap extends DS {
|
||||
$this->getValue('sasl','props'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches whether PROXY AUTH has been configured for use with a certain server.
|
||||
*
|
||||
* Users may configure phpLDAPadmin to use PROXY AUTH in config,php thus:
|
||||
* <code>
|
||||
* $servers->setValue('login','auth_type','proxy');
|
||||
* </code>
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function isProxyEnabled() {
|
||||
return $this->getValue('login','auth_type') == 'proxy' ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If PROXY AUTH is configured, then start it
|
||||
*/
|
||||
private function startProxy($resource,$method) {
|
||||
$rootdse = $this->getRootDSE();
|
||||
|
||||
if (! (isset($rootdse['supportedcontrol']) && in_array('2.16.840.1.113730.3.4.18',$rootdse['supportedcontrol']))) {
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
|
||||
'body'=>sprintf('<b>%s</b>: %s',_('Error'),_('Your LDAP server doesnt seem to support this control')),
|
||||
'type'=>'error'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$filter = '(&';
|
||||
$dn = '';
|
||||
|
||||
$missing = false;
|
||||
foreach ($this->getValue('proxy','attr') as $attr => $var) {
|
||||
if (! isset($_SERVER[$var])) {
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
|
||||
'body'=>sprintf('<b>%s</b>: %s (%s)',_('Error'),_('Attribute doesnt exist'),$var),
|
||||
'type'=>'error'));
|
||||
|
||||
$missing = true;
|
||||
|
||||
} else {
|
||||
if ($attr == 'dn') {
|
||||
$dn = $var;
|
||||
|
||||
break;
|
||||
|
||||
} else
|
||||
$filter .= sprintf('(%s=%s)',$attr,$_SERVER[$var]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($missing)
|
||||
return false;
|
||||
|
||||
$filter .= ')';
|
||||
|
||||
if (! $dn) {
|
||||
$query['filter'] = $filter;
|
||||
|
||||
foreach ($this->getBaseDN() as $base) {
|
||||
$query['base'] = $base;
|
||||
|
||||
if ($search = $this->query($query,$method))
|
||||
break;
|
||||
}
|
||||
|
||||
if (count($search) != 1) {
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
|
||||
'body'=>sprintf('<b>%s</b>: %s (%s)',_('Error'),_('Search for DN returned the incorrect number of results'),count($search)),
|
||||
'type'=>'error'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$search = array_pop($search);
|
||||
$dn = $search['dn'];
|
||||
}
|
||||
|
||||
$ctrl = array(
|
||||
'oid'=>'2.16.840.1.113730.3.4.18',
|
||||
'value'=>sprintf('dn:%s',$dn),
|
||||
'iscritical' => true);
|
||||
|
||||
if (! ldap_set_option($resource,LDAP_OPT_SERVER_CONTROLS,array($ctrl))) {
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s %s',_('Unable to start proxy connection'),$this->getName()),
|
||||
'body'=>sprintf('<b>%s</b>: %s (%s) for <b>%s</b>',_('Error'),$this->getErrorMessage($method),$this->getErrorNum($method),$method),
|
||||
'type'=>'error'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$_SESSION['USER'][$this->index][$method]['proxy'] = blowfish_encrypt($dn);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify attributes of a DN
|
||||
*/
|
||||
@ -946,6 +1059,20 @@ class ldap extends DS {
|
||||
return preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$dn);
|
||||
}
|
||||
|
||||
public function getRootDSE($method=null) {
|
||||
$query = array();
|
||||
$query['base'] = '';
|
||||
$query['scope'] = 'base';
|
||||
$query['attrs'] = $this->getValue('server','root_dse_attributes');
|
||||
$query['baseok'] = true;
|
||||
$results = $this->query($query,$method);
|
||||
|
||||
if (is_array($results))
|
||||
return array_change_key_case(array_pop($results));
|
||||
else
|
||||
return array();
|
||||
}
|
||||
|
||||
/** Schema Methods **/
|
||||
/**
|
||||
* This function will query the ldap server and request the subSchemaSubEntry which should be the Schema DN.
|
||||
|
Loading…
Reference in New Issue
Block a user