Fix SASL implementation - enabled GSSAPI

This commit is contained in:
Deon George 2011-06-20 20:30:54 +10:00
parent 5987194dec
commit afa4a95b37
6 changed files with 67 additions and 53 deletions

View File

@ -295,7 +295,7 @@ $servers->setValue('server','name','My LDAP Server');
auto-detect it for you. */ auto-detect it for you. */
// $servers->setValue('server','base',array('')); // $servers->setValue('server','base',array(''));
/* Four options for auth_type: /* Five options for auth_type:
1. 'cookie': you will login via a web form, and a client-side cookie will 1. 'cookie': you will login via a web form, and a client-side cookie will
store your login dn and password. store your login dn and password.
2. 'session': same as cookie but your login dn and password are stored on the 2. 'session': same as cookie but your login dn and password are stored on the
@ -304,6 +304,8 @@ $servers->setValue('server','name','My LDAP Server');
HTTP authentication. HTTP authentication.
4. 'config': specify your login dn and password here in this config file. No 4. 'config': specify your login dn and password here in this config file. No
login will be required to use phpLDAPadmin for this server. login will be required to use phpLDAPadmin for this server.
5. 'sasl': login will be taken from the webserver's kerberos authentication.
Currently only GSSAPI has been tested (using mod_auth_kerb).
Choose wisely to protect your authentication information appropriately for Choose wisely to protect your authentication information appropriately for
your situation. If you choose 'cookie', your cookie contents will be your situation. If you choose 'cookie', your cookie contents will be
@ -312,10 +314,11 @@ $servers->setValue('server','name','My LDAP Server');
// $servers->setValue('login','auth_type','session'); // $servers->setValue('login','auth_type','session');
/* The DN of the user for phpLDAPadmin to bind with. For anonymous binds or /* The DN of the user for phpLDAPadmin to bind with. For anonymous binds or
'cookie' or 'session' auth_types, LEAVE THE LOGIN_DN AND LOGIN_PASS BLANK. If 'cookie','session' or 'sasl' auth_types, LEAVE THE LOGIN_DN AND LOGIN_PASS
you specify a login_attr in conjunction with a cookie or session auth_type, BLANK. If you specify a login_attr in conjunction with a cookie or session
then you can also specify the bind_id/bind_pass here for searching the auth_type, then you can also specify the bind_id/bind_pass here for searching
directory for users (ie, if your LDAP server does not allow anonymous binds. */ the directory for users (ie, if your LDAP server does not allow anonymous
binds. */
// $servers->setValue('login','bind_id',''); // $servers->setValue('login','bind_id','');
# $servers->setValue('login','bind_id','cn=Manager,dc=example,dc=com'); # $servers->setValue('login','bind_id','cn=Manager,dc=example,dc=com');
@ -334,7 +337,7 @@ $servers->setValue('server','name','My LDAP Server');
/* Enable SASL authentication LDAP SASL authentication requires PHP 5.x /* Enable SASL authentication LDAP SASL authentication requires PHP 5.x
configured with --with-ldap-sasl=DIR. If this option is disabled (ie, set to configured with --with-ldap-sasl=DIR. If this option is disabled (ie, set to
false), then all other sasl options are ignored. */ false), then all other sasl options are ignored. */
// $servers->setValue('server','sasl_auth',false); // $servers->setValue('login','auth_type','sasl');
/* SASL auth mechanism */ /* SASL auth mechanism */
// $servers->setValue('server','sasl_mech','PLAIN'); // $servers->setValue('server','sasl_mech','PLAIN');
@ -528,8 +531,8 @@ $servers->setValue('login','bind_pass','');
$servers->setValue('server','tls',false); $servers->setValue('server','tls',false);
# SASL auth # SASL auth
$servers->setValue('server','sasl_auth',true); $servers->setValue('login','auth_type','sasl');
$servers->setValue('server','sasl_mech','PLAIN'); $servers->setValue('server','sasl_mech','GSSAPI');
$servers->setValue('server','sasl_realm','EXAMPLE.COM'); $servers->setValue('server','sasl_realm','EXAMPLE.COM');
$servers->setValue('server','sasl_authz_id',null); $servers->setValue('server','sasl_authz_id',null);
$servers->setValue('server','sasl_authz_id_regex','/^uid=([^,]+)(.+)/i'); $servers->setValue('server','sasl_authz_id_regex','/^uid=([^,]+)(.+)/i');

View File

@ -80,6 +80,9 @@ index uidNumber,gidNumber,loginShell eq,pres
index uid,memberUid eq,pres,sub index uid,memberUid eq,pres,sub
index nisMapName,nisMapEntry eq,pres,sub index nisMapName,nisMapEntry eq,pres,sub
sasl-regexp uid=(.*),cn=(.*),cn=gssapi,cn=auth
ldap:///dc=example.com??sub?(&(uid=$1)(objectClass=inetOrgPerson))
database bdb database bdb
suffix "o=Flintstones" suffix "o=Flintstones"
rootdn "cn=Manager,o=Flintstones" rootdn "cn=Manager,o=Flintstones"

View File

@ -328,7 +328,7 @@ class HTMLTree extends Tree {
$server = $this->getServer(); $server = $this->getServer();
$href = sprintf('cmd.php?cmd=logout&server_id=%s',$server->getIndex()); $href = sprintf('cmd.php?cmd=logout&server_id=%s',$server->getIndex());
if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','logout') || in_array($server->getAuthType(),array('config','http','proxy'))) if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','logout') || in_array($server->getAuthType(),array('config','http','proxy','sasl')))
return ''; return '';
else else
return sprintf('<a href="%s" title="%s"><img src="%s/%s" alt="%s" /><br />%s</a>', return sprintf('<a href="%s" title="%s"><img src="%s/%s" alt="%s" /><br />%s</a>',

View File

@ -368,11 +368,11 @@ abstract class DS {
$userDN = preg_replace($regex, $replacement, $_SERVER['REMOTE_USER']); $userDN = preg_replace($regex, $replacement, $_SERVER['REMOTE_USER']);
$CACHE[$this->index][$method] = $this->login($userDN, '', $method); $CACHE[$this->index][$method] = $this->login($userDN, '', $method);
}
# Otherwise, use the user name as is # Otherwise, use the user name as is
else { # For GSSAPI Authentication + mod_auth_kerb and Basic Authentication
$CACHE[$this->index][$method] = $this->login($_SERVER['REMOTE_USER'], '', $method); } else
} $CACHE[$this->index][$method] = $this->login(isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : '', '', $method);
break; break;

View File

@ -82,14 +82,9 @@ class ldap extends DS {
'default'=>array()); 'default'=>array());
# SASL configuration # SASL configuration
$this->default->server['sasl'] = array(
'desc'=>'Use SASL authentication when binding LDAP server',
'default'=>false);
$this->default->sasl['mech'] = array( $this->default->sasl['mech'] = array(
'desc'=>'SASL mechanism used while binding LDAP server', 'desc'=>'SASL mechanism used while binding LDAP server',
'untested'=>true, 'default'=>'GSSAPI');
'default'=>'PLAIN');
$this->default->sasl['realm'] = array( $this->default->sasl['realm'] = array(
'desc'=>'SASL realm name', 'desc'=>'SASL realm name',
@ -577,7 +572,7 @@ class ldap extends DS {
* *
* Users may configure phpLDAPadmin to use SASL in config,php thus: * Users may configure phpLDAPadmin to use SASL in config,php thus:
* <code> * <code>
* $servers->setValue('server','sasl',true|false); * $servers->setValue('login','auth_type','sasl');
* </code> * </code>
* *
* @return boolean * @return boolean
@ -586,12 +581,17 @@ class ldap extends DS {
if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
if ($this->getValue('server','sasl') && ! function_exists('ldap_sasl_bind')) { if ($this->getValue('login','auth_type') != 'sasl')
error(_('SASL has been enabled in your config, but your PHP install does not support SASL. SASL will be disabled.'),'warn');
return false; return false;
} else if (! function_exists('ldap_sasl_bind')) {
return $this->getValue('server','sasl'); error(_('SASL has been enabled in your config, but your PHP install does not support SASL. SASL will be disabled.'),'warn');
return false;
}
# If we get here, SASL must be configured.
return true;
} }
/** /**
@ -606,48 +606,56 @@ class ldap extends DS {
static $CACHE = array(); static $CACHE = array();
if (! $this->getValue('server','sasl') || ! function_exists('ldap_start_tls')) # We shouldnt be doing SASL binds for anonymous queries?
if ($method == 'anon')
return false; return false;
if (! isset($CACHE['login_dn'])) { # At the moment, we have only implemented GSSAPI
$CACHE['login_dn'] = is_null($this->getLogin($method)) ? $this->getLogin('user') : $this->getLogin($method); if (! in_array(strtolower($this->getValue('sasl','mech')),array('gssapi'))) {
$CACHE['login_pass'] = is_null($this->getPassword($method)) ? $this->getPassword('user') : $this->getPassword($method); system_message(array(
'title'=>_('SASL Method not implemented'),
'body'=>sprintf('<b>%s</b>: %s %s',_('Error'),$this->getValue('sasl','mech'),_('has not been implemented yet')),
'type'=>'error'));
return false;
} }
$mech = strtolower($this->getValue('sasl','mech')); if (! isset($CACHE['login_dn']))
$CACHE['login_dn'] = is_null($this->getLogin($method)) ? $this->getLogin('user') : $this->getLogin($method);
/*
# Do we need to rewrite authz_id? # Do we need to rewrite authz_id?
if (! isset($CACHE['authz_id'])) if (! isset($CACHE['authz_id']))
if (! trim($this->getValue('sasl','authz_id')) && $mech != 'gssapi') { if (! trim($this->getValue('sasl','authz_id')) && strtolower($this->getValue('sasl','mech')) != 'gssapi') {
if (DEBUG_ENABLED)
debug_log('Rewriting bind DN [%s] -> authz_id with regex [%s] and replacement [%s].',9,0,__FILE__,__LINE__,__METHOD__,
$CACHE['login_dn'],
$this->getValue('sasl','authz_id_regex'),
$this->getValue('sasl','authz_id_replacement'));
if (DEBUG_ENABLED) $CACHE['authz_id'] = @preg_replace($this->getValue('sasl','authz_id_regex'),
debug_log('Rewriting bind DN [%s] -> authz_id with regex [%s] and replacement [%s].',9,0,__FILE__,__LINE__,__METHOD__, $this->getValue('sasl','authz_id_replacement'),$CACHE['login_dn']);
$CACHE['login_dn'],
$this->getValue('sasl','authz_id_regex'),
$this->getValue('sasl','authz_id_replacement'));
$CACHE['authz_id'] = @preg_replace($this->getValue('sasl','authz_id_regex'), # Invalid regex?
$this->getValue('sasl','authz_id_replacement'),$CACHE['login_dn']); if (is_null($CACHE['authz_id']))
error(sprintf(_('It seems that sasl_authz_id_regex "%s" contains invalid PCRE regular expression. The error is "%s".'),
$this->getValue('sasl','authz_id_regex'),(isset($php_errormsg) ? $php_errormsg : '')),
'error','index.php');
# Invalid regex? if (DEBUG_ENABLED)
if (is_null($CACHE['authz_id'])) debug_log('Resource [%s], SASL OPTIONS: mech [%s], realm [%s], authz_id [%s], props [%s]',9,0,__FILE__,__LINE__,__METHOD__,
error(sprintf(_('It seems that sasl_authz_id_regex "%s" contains invalid PCRE regular expression. The error is "%s".'), $resource,
$this->getValue('sasl','authz_id_regex'),(isset($php_errormsg) ? $php_errormsg : '')), $this->getValue('sasl','mech'),
'error','index.php'); $this->getValue('sasl','realm'),
$CACHE['authz_id'],
if (DEBUG_ENABLED) $this->getValue('sasl','props'));
debug_log('Resource [%s], SASL OPTIONS: mech [%s], realm [%s], authz_id [%s], props [%s]',9,0,__FILE__,__LINE__,__METHOD__,
$resource,
$this->getValue('sasl','mech'),
$this->getValue('sasl','realm'),
$CACHE['authz_id'],
$this->getValue('sasl','props'));
} else } else
$CACHE['authz_id'] = $this->getValue('sasl','authz_id'); $CACHE['authz_id'] = $this->getValue('sasl','authz_id');
*/
# @todo this function is different in PHP5.1 and PHP5.2 # @todo this function is different in PHP5.1 and PHP5.2
return @ldap_sasl_bind($resource,$CACHE['login_dn'],$CACHE['login_pass'], return @ldap_sasl_bind($resource,NULL,'',
$this->getValue('sasl','mech'), $this->getValue('sasl','mech'),
$this->getValue('sasl','realm'), $this->getValue('sasl','realm'),
$CACHE['authz_id'], $CACHE['authz_id'],

View File

@ -745,7 +745,7 @@ function blowfish_encrypt($data,$secret=null) {
if (! trim($secret)) if (! trim($secret))
return $data; return $data;
if (function_exists('mcrypt_module_open')) { if (function_exists('mcrypt_module_open') && trim($data)) {
$td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,''); $td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,'');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM); $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM);
mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv); mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv);
@ -800,7 +800,7 @@ function blowfish_decrypt($encdata,$secret=null) {
if (! trim($secret)) if (! trim($secret))
return $encdata; return $encdata;
if (function_exists('mcrypt_module_open')) { if (function_exists('mcrypt_module_open') && trim($encdata)) {
$td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,''); $td = mcrypt_module_open(MCRYPT_BLOWFISH,'',MCRYPT_MODE_ECB,'');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM); $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM);
mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv); mcrypt_generic_init($td,substr($secret,0,mcrypt_enc_get_key_size($td)),$iv);