ajout modules PEAR ldap pour test

This commit is contained in:
Regis Houssin 2006-06-25 20:18:56 +00:00
parent 556361237f
commit 294fa50fa0
4 changed files with 1951 additions and 0 deletions

View File

@ -0,0 +1,525 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license <at> php <dot> net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Jan Wagner <wagner <at> netsols <dot> de> |
// +----------------------------------------------------------------------+
//
// $Id$
//
require_once DOL_DOCUMENT_ROOT."/includes/pear/Auth/Container.php";
require_once DOL_DOCUMENT_ROOT."/includes/pear/PEAR.php";
/**
* Storage driver for fetching login data from LDAP
*
* This class is heavily based on the DB and File containers. By default it
* connects to localhost:389 and searches for uid=$username with the scope
* "sub". If no search base is specified, it will try to determine it via
* the namingContexts attribute. It takes its parameters in a hash, connects
* to the ldap server, binds anonymously, searches for the user, and tries
* to bind as the user with the supplied password. When a group was set, it
* will look for group membership of the authenticated user. If all goes
* well the authentication was successful.
*
* Parameters:
*
* host: localhost (default), ldap.netsols.de or 127.0.0.1
* port: 389 (default) or 636 or whereever your server runs
* url: ldap://localhost:389/
* useful for ldaps://, works only with openldap2 ?
* it will be preferred over host and port
* version: LDAP version to use, ususally 2 (default) or 3,
* must be an integer!
* binddn: If set, searching for user will be done after binding
* as this user, if not set the bind will be anonymous.
* This is reported to make the container work with MS
* Active Directory, but should work with any server that
* is configured this way.
* This has to be a complete dn for now (basedn and
* userdn will not be appended).
* bindpw: The password to use for binding with binddn
* basedn: the base dn of your server
* userdn: gets prepended to basedn when searching for user
* userscope: Scope for user searching: one, sub (default), or base
* userattr: the user attribute to search for (default: uid)
* userfilter: filter that will be added to the search filter
* this way: (&(userattr=username)(userfilter))
* default: (objectClass=posixAccount)
* attributes: array of additional attributes to fetch from entry.
* these will added to auth data and can be retrieved via
* Auth::getAuthData(). An empty array will fetch all attributes,
* array('') will fetch no attributes at all (default)
* groupdn: gets prepended to basedn when searching for group
* groupattr: the group attribute to search for (default: cn)
* groupfilter: filter that will be added to the search filter when
* searching for a group:
* (&(groupattr=group)(memberattr=username)(groupfilter))
* default: (objectClass=groupOfUniqueNames)
* memberattr : the attribute of the group object where the user dn
* may be found (default: uniqueMember)
* memberisdn: whether the memberattr is the dn of the user (default)
* or the value of userattr (usually uid)
* group: the name of group to search for
* groupscope: Scope for group searching: one, sub (default), or base
* debug: Enable/Disable debugging output (default: false)
*
* To use this storage container, you have to use the following syntax:
*
* <?php
* ...
*
* $a = new Auth("LDAP", array(
* 'host' => 'localhost',
* 'port' => '389',
* 'version' => 3,
* 'basedn' => 'o=netsols, c=de',
* 'userattr' => 'uid'
* 'binddn' => 'cn=admin, o=netsols, c=de',
* 'bindpw' => 'password'));
*
* $a2 = new Auth('LDAP', array(
* 'url' => 'ldaps://ldap.netsols.de',
* 'basedn' => 'o=netsols, c=de',
* 'userscope' => 'one',
* 'userdn' => 'ou=People',
* 'groupdn' => 'ou=Groups',
* 'groupfilter' => '(objectClass=posixGroup)',
* 'memberattr' => 'memberUid',
* 'memberisdn' => false,
* 'group' => 'admin'
* ));
*
* This is a full blown example with user/group checking to an Active Directory
*
* $a3 = new Auth('LDAP', array(
* 'host' => 'ldap.netsols.de',
* 'port' => 389,
* 'version' => 3,
* 'basedn' => 'dc=netsols, dc=de',
* 'binddn' => 'cn=Jan Wagner, cn=Users, dc=netsols, dc=de',
* 'bindpw' => 'password',
* 'userattr' => 'samAccountName',
* 'userfilter' => '(objectClass=user)',
* 'attributes' => array(''),
* 'group' => 'testing',
* 'groupattr' => 'samAccountName',
* 'groupfilter' => '(objectClass=group)',
* 'memberattr' => 'member',
* 'memberisdn' => true,
* 'groupdn' => 'cn=Users',
* 'groupscope' => 'one',
* 'debug' => true);
*
* The parameter values have to correspond
* to the ones for your LDAP server of course.
*
* When talking to a Microsoft ActiveDirectory server you have to
* use 'samaccountname' as the 'userattr' and follow special rules
* to translate the ActiveDirectory directory names into 'basedn'.
* The 'basedn' for the default 'Users' folder on an ActiveDirectory
* server for the ActiveDirectory Domain (which is not related to
* its DNS name) "win2000.example.org" would be:
* "CN=Users, DC=win2000, DC=example, DC=org'
* where every component of the domain name becomes a DC attribute
* of its own. If you want to use a custom users folder you have to
* replace "CN=Users" with a sequence of "OU" attributes that specify
* the path to your custom folder in reverse order.
* So the ActiveDirectory folder
* "win2000.example.org\Custom\Accounts"
* would become
* "OU=Accounts, OU=Custom, DC=win2000, DC=example, DC=org'
*
* It seems that binding anonymously to an Active Directory
* is not allowed, so you have to set binddn and bindpw for
* user searching,
*
* Example a3 shows a tested example for connenction to Windows 2000
* Active Directory
*
* @author Jan Wagner <wagner <at> netsols <dot> de>
* @package Auth
* @version $Revision$
*/
class Auth_Container_LDAP extends Auth_Container
{
/**
* Options for the class
* @var array
*/
var $options = array();
/**
* Connection ID of LDAP Link
* @var string
*/
var $conn_id = false;
/**
* Constructor of the container class
*
* @param $params, associative hash with host, port, basedn and userattr key
* @return object Returns an error object if something went wrong
*/
function Auth_Container_LDAP($params)
{
if (false === extension_loaded('ldap')) {
return PEAR::raiseError('Auth_Container_LDAP: LDAP Extension not loaded', 41, PEAR_ERROR_DIE);
}
$this->_setDefaults();
if (is_array($params)) {
$this->_parseOptions($params);
}
}
// }}}
// {{{ _connect()
/**
* Connect to the LDAP server using the global options
*
* @access private
* @return object Returns a PEAR error object if an error occurs.
*/
function _connect()
{
// connect
if (isset($this->options['url']) && $this->options['url'] != '') {
$this->_debug('Connecting with URL', __LINE__);
$conn_params = array($this->options['url']);
} else {
$this->_debug('Connecting with host:port', __LINE__);
$conn_params = array($this->options['host'], $this->options['port']);
}
if (($this->conn_id = @call_user_func_array('ldap_connect', $conn_params)) === false) {
return PEAR::raiseError('Auth_Container_LDAP: Could not connect to server.', 41, PEAR_ERROR_DIE);
}
$this->_debug('Successfully connected to server', __LINE__);
// switch LDAP version
if (is_int($this->options['version']) && $this->options['version'] > 2) {
$this->_debug("Switching to LDAP version {$this->options['version']}", __LINE__);
@ldap_set_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $this->options['version']);
}
// bind with credentials or anonymously
if ($this->options['binddn'] && $this->options['bindpw']) {
$this->_debug('Binding with credentials', __LINE__);
$bind_params = array($this->conn_id, $this->options['binddn'], $this->options['bindpw']);
} else {
$this->_debug('Binding anonymously', __LINE__);
$bind_params = array($this->conn_id);
}
// bind for searching
if ((@call_user_func_array('ldap_bind', $bind_params)) == false) {
$this->_debug();
$this->_disconnect();
return PEAR::raiseError("Auth_Container_LDAP: Could not bind to LDAP server.", 41, PEAR_ERROR_DIE);
}
$this->_debug('Binding was successful', __LINE__);
}
/**
* Disconnects (unbinds) from ldap server
*
* @access private
*/
function _disconnect()
{
if ($this->_isValidLink()) {
$this->_debug('disconnecting from server');
@ldap_unbind($this->conn_id);
}
}
/**
* Tries to find Basedn via namingContext Attribute
*
* @access private
*/
function _getBaseDN()
{
if ($this->options['basedn'] == "" && $this->_isValidLink()) {
$this->_debug("basedn not set, searching via namingContexts.", __LINE__);
$result_id = @ldap_read($this->conn_id, "", "(objectclass=*)", array("namingContexts"));
if (@ldap_count_entries($this->conn_id, $result_id) == 1) {
$this->_debug("got result for namingContexts", __LINE__);
$entry_id = @ldap_first_entry($this->conn_id, $result_id);
$attrs = @ldap_get_attributes($this->conn_id, $entry_id);
$basedn = $attrs['namingContexts'][0];
if ($basedn != "") {
$this->_debug("result for namingContexts was $basedn", __LINE__);
$this->options['basedn'] = $basedn;
}
}
@ldap_free_result($result_id);
}
// if base ist still not set, raise error
if ($this->options['basedn'] == "") {
return PEAR::raiseError("Auth_Container_LDAP: LDAP search base not specified!", 41, PEAR_ERROR_DIE);
}
return true;
}
/**
* determines whether there is a valid ldap conenction or not
*
* @accessd private
* @return boolean
*/
function _isValidLink()
{
if (is_resource($this->conn_id)) {
if (get_resource_type($this->conn_id) == 'ldap link') {
return true;
}
}
return false;
}
/**
* Set some default options
*
* @access private
*/
function _setDefaults()
{
$this->options['url'] = '';
$this->options['host'] = 'localhost';
$this->options['port'] = '389';
$this->options['version'] = 2;
$this->options['binddn'] = '';
$this->options['bindpw'] = '';
$this->options['basedn'] = '';
$this->options['userdn'] = '';
$this->options['userscope'] = 'sub';
$this->options['userattr'] = "uid";
$this->options['userfilter'] = '(objectClass=posixAccount)';
$this->options['attributes'] = array(''); // no attributes
$this->options['group'] = '';
$this->options['groupdn'] = '';
$this->options['groupscope'] = 'sub';
$this->options['groupattr'] = 'cn';
$this->options['groupfilter'] = '(objectClass=groupOfUniqueNames)';
$this->options['memberattr'] = 'uniqueMember';
$this->options['memberisdn'] = true;
$this->options['debug'] = false;
}
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (array_key_exists($key, $this->options)) {
$this->options[$key] = $value;
}
}
}
/**
* Get search function for scope
*
* @param string scope
* @return string ldap search function
*/
function _scope2function($scope)
{
switch($scope) {
case 'one':
$function = 'ldap_list';
break;
case 'base':
$function = 'ldap_read';
break;
default:
$function = 'ldap_search';
break;
}
return $function;
}
/**
* Fetch data from LDAP server
*
* Searches the LDAP server for the given username/password
* combination.
*
* @param string Username
* @param string Password
* @return boolean
*/
function fetchData($username, $password)
{
$this->_connect();
$this->_getBaseDN();
// UTF8 Encode username for LDAPv3
if (@ldap_get_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $ver) && $ver == 3) {
$this->_debug('UTF8 encoding username for LDAPv3', __LINE__);
$username = utf8_encode($username);
}
// make search filter
$filter = sprintf('(&(%s=%s)%s)',
$this->options['userattr'],
$username,
$this->options['userfilter']);
// make search base dn
$search_basedn = $this->options['userdn'];
if ($search_basedn != '' && substr($search_basedn, -1) != ', ') {
$search_basedn .= ', ';
}
$search_basedn .= $this->options['basedn'];
// attributes
$attributes = $this->options['attributes'];
// make functions params array
$func_params = array($this->conn_id, $search_basedn, $filter, $attributes);
// search function to use
$func_name = $this->_scope2function($this->options['userscope']);
$this->_debug("Searching with $func_name and filter $filter in $search_basedn", __LINE__);
// search
if (($result_id = @call_user_func_array($func_name, $func_params)) == false) {
$this->_debug('User not found', __LINE__);
} elseif (@ldap_count_entries($this->conn_id, $result_id) == 1) { // did we get just one entry?
$this->_debug('User was found', __LINE__);
// then get the user dn
$entry_id = @ldap_first_entry($this->conn_id, $result_id);
$user_dn = @ldap_get_dn($this->conn_id, $entry_id);
// fetch attributes
if ($attributes = @ldap_get_attributes($this->conn_id, $entry_id)) {
if (is_array($attributes) && isset($attributes['count']) &&
$attributes['count'] > 0)
{
$this->_debug('Saving attributes to Auth data', __LINE__);
$this->_auth_obj->setAuthData('attributes', $attributes);
}
}
@ldap_free_result($result_id);
// need to catch an empty password as openldap seems to return TRUE
// if anonymous binding is allowed
if ($password != "") {
$this->_debug("Bind as $user_dn", __LINE__);
// try binding as this user with the supplied password
if (@ldap_bind($this->conn_id, $user_dn, $password)) {
$this->_debug('Bind successful', __LINE__);
// check group if appropiate
if (strlen($this->options['group'])) {
// decide whether memberattr value is a dn or the username
$this->_debug('Checking group membership', __LINE__);
return $this->checkGroup(($this->options['memberisdn']) ? $user_dn : $username);
} else {
$this->_debug('Authenticated', __LINE__);
$this->_disconnect();
return true; // user authenticated
} // checkGroup
} // bind
} // non-empty password
} // one entry
// default
$this->_debug('NOT authenticated!', __LINE__);
$this->_disconnect();
return false;
}
/**
* Validate group membership
*
* Searches the LDAP server for group membership of the
* authenticated user
*
* @param string Distinguished Name of the authenticated User
* @return boolean
*/
function checkGroup($user)
{
// make filter
$filter = sprintf('(&(%s=%s)(%s=%s)%s)',
$this->options['groupattr'],
$this->options['group'],
$this->options['memberattr'],
$user,
$this->options['groupfilter']);
// make search base dn
$search_basedn = $this->options['groupdn'];
if ($search_basedn != '' && substr($search_basedn, -1) != ', ') {
$search_basedn .= ', ';
}
$search_basedn .= $this->options['basedn'];
$func_params = array($this->conn_id, $search_basedn, $filter,
array($this->options['memberattr']));
$func_name = $this->_scope2function($this->options['groupscope']);
$this->_debug("Searching with $func_name and filter $filter in $search_basedn", __LINE__);
// search
if (($result_id = @call_user_func_array($func_name, $func_params)) != false) {
if (@ldap_count_entries($this->conn_id, $result_id) == 1) {
@ldap_free_result($result_id);
$this->_debug('User is member of group', __LINE__);
$this->_disconnect();
return true;
}
}
// default
$this->_debug('User is NOT member of group', __LINE__);
$this->_disconnect();
return false;
}
/**
* Outputs debugging messages
*
* @access private
* @param string Debugging Message
* @param integer Line number
*/
function _debug($msg = '', $line = 0)
{
if ($this->options['debug'] === true) {
if ($msg == '' && $this->_isValidLink()) {
$msg = 'LDAP_Error: ' . @ldap_err2str(@ldap_errno($this->_conn_id));
}
print("$line: $msg <br />");
}
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
<?php
//
// Pear DB LDAP3 - Database independent query interface definition
// for PHP's LDAP extension with protocol version 3.
//
// Copyright (C) 2002-2003 Piotr Roszatycki <dexter@debian.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// $Id$
//
require_once DOL_DOCUMENT_ROOT."/includes/pear/DB/common.php";
require_once DOL_DOCUMENT_ROOT."/includes/pear/DB/ldap2.php";
/**
* LDAP3 DB interface class
*
* DB_ldap3 extends DB_ldap2 to provide DB compliant
* access to LDAP servers with protocol version 3.
*
* @author Piotr Roszatycki <dexter@debian.org>
* @version $Revision$
* @package DB_ldap3
*/
class DB_ldap3 extends DB_ldap2
{
// {{{ connect()
/**
* Connect and bind to LDAPv3 server with either anonymous
* or authenticated bind depending on dsn info
*
* The format of the supplied DSN:
*
* ldap3://binddn:bindpw@host:port/basedn
*
* I.e.:
*
* ldap3://uid=dexter,ou=People,dc=example,dc=net:secret@127.0.0.1/dc=example,dc=net
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param boolean $persistent kept for interface compatibility
* @return int DB_OK if successfully connected.
* A DB error code is returned on failure.
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('ldap'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$type = $dsninfo['phptype'];
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$host = $dsninfo['hostspec'];
$port = empty($dsninfo['port']) ? 389 : $dsninfo['port'];
$this->param = array(
'action' => 'search',
'base_dn' => $this->base_dn = $dsninfo['database'],
'attributes' => array(),
'attrsonly' => 0,
'sizelimit' => 0,
'timelimit' => 0,
'deref' => LDAP_DEREF_NEVER,
'attribute' => '',
'value' => '',
'newrdn' => '',
'newparent' => '',
'deleteoldrdn'=>false,
'sort' => '',
);
$this->last_param = $this->param;
$this->setOption("seqname_format", "sn=%s," . $dsninfo['database']);
$this->fetchmode = DB_FETCHMODE_ASSOC;
if ($host) {
$conn = @ldap_connect($host, $port);
} else {
return $this->raiseError("unknown host $host");
}
if (!$conn) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
}
if (!@ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
}
if ($user && $pw) {
$bind = @ldap_bind($conn, $user, $pw);
} else {
$bind = @ldap_bind($conn);
}
if (!$bind) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
}
$this->connection = $conn;
return DB_OK;
}
// }}}
}
?>

View File

@ -105,6 +105,7 @@ elseif (! empty($_SERVER["REMOTE_USER"]))
$_SESSION["dol_user"]=$user;
}
}
// MODE 3: Identification depuis base de donnees
else
{
@ -152,7 +153,69 @@ else
exit;
}
}
/*
// MODE 4: Identification depuis ldap
else
{
if($conf->ldap->enabled)
{
// Authentification Apache KO ou non active, pas de mode force on demande le login
require_once(DOL_DOCUMENT_ROOT."/includes/pear/Auth/Auth.php");
//if ($conf->global->LDAP_SERVER_PROTOCOLVERSION == 3)
//{
$ldap = 'ldap://'.$conf->global->LDAP_ADMIN_DN.':'.$conf->global->LDAP_ADMIN_PASS.'@'.$conf->global->LDAP_SERVER_HOST.':'.$conf->global->LDAP_SERVER_PORT.'/'.$conf->global->LDAP_SERVER_DN;
//}
//else
//{
// $ldap = 'ldap2://'.$conf->global->LDAP_ADMIN_DN.':'.$conf->global->LDAP_ADMIN_PASS.'@'.$conf->global->LDAP_SERVER_HOST.':'.$conf->global->LDAP_SERVER_PORT.'/'.$conf->global->LDAP_SERVER_DN;
//}
$params = array(
'dsn' => $ldap,
'host' => $conf->global->LDAP_SERVER_HOST,
'port' => $conf->global->LDAP_SERVER_PORT,
'version' => $conf->global->LDAP_SERVER_PORT,
'basedn' => $conf->global->LDAP_SERVER_DN,
'binddn' => $conf->global->LDAP_ADMIN_DN,
'bindpw' => $conf->global->LDAP_ADMIN_PASS,
'userattr' => $conf->global->LDAP_FIELD_LOGIN_SAMBA,
'userfilter' => '(objectClass=user)',
);
$aDol = new DOLIAuth("DB", $params, "loginfunction");
$aDol->setSessionName("DOLSESSID_".$dolibarr_main_db_name);
$aDol->start();
$result = $aDol->getAuth();
if ($result)
{
// Authentification Auth OK, on va chercher les infos du user
$user->fetch($aDol->getUsername());
dolibarr_syslog ("Authentification ok (en mode Pear)");
if (isset($_POST["loginfunction"]))
{
// Si phase de login initial
$user->update_last_login_date();
}
}
else
{
if (isset($_POST["loginfunction"]))
{
// Echec authentification
dolibarr_syslog("Authentification ko (en mode Pear) pour '".$_POST["username"]."'");
}
else
{
// Non authentifie dolibarr_syslog("Authentification non realise;
}
// Le debut de la page a ete affiche par loginfunction. On ferme juste la page
print "</div>\n</div>\n</body>\n</html>";
exit;
}
}
}
*/
// Si user admin, on force droits sur les modules base
if ($user->admin)
{