diff --git a/config/config.php.example b/config/config.php.example index a8a0d06..fb66364 100644 --- a/config/config.php.example +++ b/config/config.php.example @@ -295,7 +295,7 @@ $servers->setValue('server','name','My LDAP Server'); auto-detect it for you. */ // $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 store your login dn and password. 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. 4. 'config': specify your login dn and password here in this config file. No 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 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'); /* 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 - you specify a login_attr in conjunction with a cookie or session auth_type, - then you can also specify the bind_id/bind_pass here for searching the - directory for users (ie, if your LDAP server does not allow anonymous binds. */ + 'cookie','session' or 'sasl' auth_types, LEAVE THE LOGIN_DN AND LOGIN_PASS + BLANK. If you specify a login_attr in conjunction with a cookie or session + auth_type, then you can also specify the bind_id/bind_pass here for searching + the directory for users (ie, if your LDAP server does not allow anonymous + binds. */ // $servers->setValue('login','bind_id',''); # $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 configured with --with-ldap-sasl=DIR. If this option is disabled (ie, set to false), then all other sasl options are ignored. */ -// $servers->setValue('server','sasl_auth',false); +// $servers->setValue('login','auth_type','sasl'); /* SASL auth mechanism */ // $servers->setValue('server','sasl_mech','PLAIN'); @@ -528,8 +531,8 @@ $servers->setValue('login','bind_pass',''); $servers->setValue('server','tls',false); # SASL auth -$servers->setValue('server','sasl_auth',true); -$servers->setValue('server','sasl_mech','PLAIN'); +$servers->setValue('login','auth_type','sasl'); +$servers->setValue('server','sasl_mech','GSSAPI'); $servers->setValue('server','sasl_realm','EXAMPLE.COM'); $servers->setValue('server','sasl_authz_id',null); $servers->setValue('server','sasl_authz_id_regex','/^uid=([^,]+)(.+)/i'); diff --git a/doc/phpldapadmin-demo.conf b/doc/phpldapadmin-demo.conf index a45ddb9..3ed4063 100644 --- a/doc/phpldapadmin-demo.conf +++ b/doc/phpldapadmin-demo.conf @@ -80,6 +80,9 @@ index uidNumber,gidNumber,loginShell eq,pres index uid,memberUid 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 suffix "o=Flintstones" rootdn "cn=Manager,o=Flintstones" diff --git a/lib/HTMLTree.php b/lib/HTMLTree.php index 506b938..90861cb 100644 --- a/lib/HTMLTree.php +++ b/lib/HTMLTree.php @@ -328,7 +328,7 @@ class HTMLTree extends Tree { $server = $this->getServer(); $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 ''; else return sprintf('%s
%s
', diff --git a/lib/ds.php b/lib/ds.php index 8b170fd..e7f4589 100644 --- a/lib/ds.php +++ b/lib/ds.php @@ -368,11 +368,11 @@ abstract class DS { $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); - } + # For GSSAPI Authentication + mod_auth_kerb and Basic Authentication + } else + $CACHE[$this->index][$method] = $this->login(isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : '', '', $method); break; diff --git a/lib/ds_ldap.php b/lib/ds_ldap.php index 834813e..5849c4b 100644 --- a/lib/ds_ldap.php +++ b/lib/ds_ldap.php @@ -82,14 +82,9 @@ class ldap extends DS { 'default'=>array()); # SASL configuration - $this->default->server['sasl'] = array( - 'desc'=>'Use SASL authentication when binding LDAP server', - 'default'=>false); - $this->default->sasl['mech'] = array( 'desc'=>'SASL mechanism used while binding LDAP server', - 'untested'=>true, - 'default'=>'PLAIN'); + 'default'=>'GSSAPI'); $this->default->sasl['realm'] = array( 'desc'=>'SASL realm name', @@ -577,7 +572,7 @@ class ldap extends DS { * * Users may configure phpLDAPadmin to use SASL in config,php thus: * - * $servers->setValue('server','sasl',true|false); + * $servers->setValue('login','auth_type','sasl'); * * * @return boolean @@ -586,12 +581,17 @@ class ldap extends DS { if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS')) debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs); - if ($this->getValue('server','sasl') && ! function_exists('ldap_sasl_bind')) { - error(_('SASL has been enabled in your config, but your PHP install does not support SASL. SASL will be disabled.'),'warn'); + if ($this->getValue('login','auth_type') != 'sasl') return false; - } else - return $this->getValue('server','sasl'); + if (! function_exists('ldap_sasl_bind')) { + 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(); - if (! $this->getValue('server','sasl') || ! function_exists('ldap_start_tls')) + # We shouldnt be doing SASL binds for anonymous queries? + if ($method == 'anon') return false; - if (! isset($CACHE['login_dn'])) { - $CACHE['login_dn'] = is_null($this->getLogin($method)) ? $this->getLogin('user') : $this->getLogin($method); - $CACHE['login_pass'] = is_null($this->getPassword($method)) ? $this->getPassword('user') : $this->getPassword($method); + # At the moment, we have only implemented GSSAPI + if (! in_array(strtolower($this->getValue('sasl','mech')),array('gssapi'))) { + system_message(array( + 'title'=>_('SASL Method not implemented'), + 'body'=>sprintf('%s: %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? 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) - 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')); + $CACHE['authz_id'] = @preg_replace($this->getValue('sasl','authz_id_regex'), + $this->getValue('sasl','authz_id_replacement'),$CACHE['login_dn']); - $CACHE['authz_id'] = @preg_replace($this->getValue('sasl','authz_id_regex'), - $this->getValue('sasl','authz_id_replacement'),$CACHE['login_dn']); + # Invalid regex? + 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 (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'); - - if (DEBUG_ENABLED) - 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')); + if (DEBUG_ENABLED) + 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 $CACHE['authz_id'] = $this->getValue('sasl','authz_id'); + */ # @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','realm'), $CACHE['authz_id'], diff --git a/lib/functions.php b/lib/functions.php index d26813a..1afac21 100644 --- a/lib/functions.php +++ b/lib/functions.php @@ -745,7 +745,7 @@ function blowfish_encrypt($data,$secret=null) { if (! trim($secret)) 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,''); $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); @@ -800,7 +800,7 @@ function blowfish_decrypt($encdata,$secret=null) { if (! trim($secret)) 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,''); $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);