Implemented better SASL/GSSAPI authentication.

Implemented a 'sasl' auth_type for better control over authentication
flow specific to SASL.

Implemented 'sasl_dn_regex' and 'sasl_dn_replacement' config variables
for mapping from a SASL authentication ID to a bind DN, a necessary step
when using GSSAPI/Kerberos where there is no explicit bind DN provided.

Fixed setting of Kerberos credentials cache location in environment
variable. The location is derived from either an already set
environement variable or the SERVER variable set by the Apache
mod_auth_kerb module.
See http://modauthkerb.sourceforge.net/configure.html
This commit is contained in:
Dan Duvall 2010-07-09 18:01:47 -07:00 committed by Deon George
parent 7980d1c131
commit b3874bf958
3 changed files with 43 additions and 9 deletions

View File

@ -133,6 +133,7 @@ class HTMLTree extends Tree {
case 'config': case 'config':
case 'proxy': case 'proxy':
case 'sasl':
break; break;
default: default:

View File

@ -137,6 +137,7 @@ abstract class DS {
case 'http': case 'http':
case 'proxy': case 'proxy':
case 'session': case 'session':
case 'sasl':
return $this->getValue('login','auth_type'); return $this->getValue('login','auth_type');
default: default:
@ -178,6 +179,7 @@ abstract class DS {
case 'http': case 'http':
case 'session': case 'session':
case 'sasl':
if (! isset($_SESSION['USER'][$this->index][$method]['name'])) if (! isset($_SESSION['USER'][$this->index][$method]['name']))
# If our bind_id is set, we'll pass that back for logins. # If our bind_id is set, we'll pass that back for logins.
return (! is_null($this->getValue('login','bind_id')) && $method == 'login') ? $this->getValue('login','bind_id') : null; return (! is_null($this->getValue('login','bind_id')) && $method == 'login') ? $this->getValue('login','bind_id') : null;
@ -208,6 +210,7 @@ abstract class DS {
case 'http': case 'http':
case 'session': case 'session':
case 'sasl':
$_SESSION['USER'][$this->index][$method]['name'] = blowfish_encrypt($user); $_SESSION['USER'][$this->index][$method]['name'] = blowfish_encrypt($user);
$_SESSION['USER'][$this->index][$method]['pass'] = blowfish_encrypt($pass); $_SESSION['USER'][$this->index][$method]['pass'] = blowfish_encrypt($pass);
@ -244,6 +247,7 @@ abstract class DS {
case 'http': case 'http':
case 'session': case 'session':
case 'sasl':
if (! isset($_SESSION['USER'][$this->index][$method]['pass'])) if (! isset($_SESSION['USER'][$this->index][$method]['pass']))
# If our bind_pass is set, we'll pass that back for logins. # If our bind_pass is set, we'll pass that back for logins.
return (! is_null($this->getValue('login','bind_pass')) && $method == 'login') ? $this->getValue('login','bind_pass') : null; return (! is_null($this->getValue('login','bind_pass')) && $method == 'login') ? $this->getValue('login','bind_pass') : null;
@ -329,6 +333,29 @@ abstract class DS {
break; break;
case 'sasl':
# Propogate any given Kerberos credential cache location
if (isset($_ENV['REDIRECT_KRB5CCNAME']))
putenv(sprintf('KRB5CCNAME=%s',$_ENV['REDIRECT_KRB5CCNAME']));
elseif (isset($_SERVER['KRB5CCNAME']))
putenv(sprintf('KRB5CCNAME=%s',$_SERVER['KRB5CCNAME']));
# Map the SASL auth ID to a DN
$regex = $this->getValue('login', 'sasl_dn_regex');
$replacement = $this->getValue('login', 'sasl_dn_replacement');
if ($regex && $replacement) {
$userDN = preg_replace($regex, $replacement, $_SERVER['REMOTE_USER']);
$CACHE[$this->index][$method] = $this->login($userDN, '', $method);
}
# Otherwise, use the user name as is
else {
$CACHE[$this->index][$method] = $this->login($_SERVER['REMOTE_USER'], '', $method);
}
break;
default: default:
$CACHE[$this->index][$method] = is_null($this->getLogin($method)) ? false : true; $CACHE[$this->index][$method] = is_null($this->getLogin($method)) ? false : true;
} }
@ -354,6 +381,7 @@ abstract class DS {
case 'http': case 'http':
case 'proxy': case 'proxy':
case 'session': case 'session':
case 'sasl':
if (isset($_SESSION['USER'][$this->index][$method])) if (isset($_SESSION['USER'][$this->index][$method]))
unset($_SESSION['USER'][$this->index][$method]); unset($_SESSION['USER'][$this->index][$method]);
@ -526,6 +554,17 @@ class Datastore {
'desc'=>'Session timout in seconds', 'desc'=>'Session timout in seconds',
'default'=>session_cache_expire()-1); 'default'=>session_cache_expire()-1);
$this->default->login['sasl_dn_regex'] = array(
'desc'=>'SASL authorization id to user dn PCRE regular expression',
'untested'=>true,
'default'=>null);
$this->default->login['sasl_dn_replacement'] = array(
'desc'=>'SASL authorization id to user dn PCRE regular expression replacement string',
'untested'=>true,
'default'=>null);
# Prefix for custom pages # Prefix for custom pages
$this->default->custom['pages_prefix'] = array( $this->default->custom['pages_prefix'] = array(
'desc'=>'Prefix name for custom pages', 'desc'=>'Prefix name for custom pages',

View File

@ -605,14 +605,6 @@ class ldap extends DS {
static $CACHE = array(); static $CACHE = array();
switch (strtolower($this->getValue('sasl','mech'))) {
case 'gssapi':
if (isset($_ENV['REDIRECT_KRB5CCNAME']))
putenv(sprintf('KRB5CCNAME={%s}',$_ENV['REDIRECT_KRB5CCNAME']));
break;
}
if (! $this->getValue('server','sasl') || ! function_exists('ldap_start_tls')) if (! $this->getValue('server','sasl') || ! function_exists('ldap_start_tls'))
return false; return false;
@ -621,9 +613,11 @@ class ldap extends DS {
$CACHE['login_pass'] = is_null($this->getPassword($method)) ? $this->getPassword('user') : $this->getPassword($method); $CACHE['login_pass'] = is_null($this->getPassword($method)) ? $this->getPassword('user') : $this->getPassword($method);
} }
$mech = strtolower($this->getValue('sasl','mech'));
# 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'))) { if (! trim($this->getValue('sasl','authz_id')) && $mech != 'gssapi') {
if (DEBUG_ENABLED) if (DEBUG_ENABLED)
debug_log('Rewriting bind DN [%s] -> authz_id with regex [%s] and replacement [%s].',9,0,__FILE__,__LINE__,__METHOD__, debug_log('Rewriting bind DN [%s] -> authz_id with regex [%s] and replacement [%s].',9,0,__FILE__,__LINE__,__METHOD__,