It is my first PHP "development" and first post to a public forum. So I am a bit shy... Time to share experience!
I have just finished the first version of a small hack to use our internal user directory accessible through LDAP for XOOPS user authentication.
The goal is to allow all users registered in the Directory to directly connect to Xoops, without having to register manually
BUT WITHOUT preventing users not present in the central Directory to register. How is it working ?
In fact, I simply automatically register the users that I can authenticate through LDAP and then let the normal authentication process continue.
2 files have to be modified:
Add these 3 lines at the very beginning of the &loginUser($uname, $pwd) function in /kernel/member.php $ldap_criteria = new CriteriaCompo(new Criteria('uname', $uname));
$ldap_criteria->add(new Criteria('pass', $pwd));
$authenticated = $this->_uHandler->LDAPAuthentication($ldap_criteria, false);
Add the following function to the XoopsUserHandler class in /kernel/user.php /**
* retrieve users from a Directory server through LDAP
* @param object $criteria {@link CriteriaElement} conditions to be met
* @return true if the user has been authenticated, otherwise false
*/
function LDAPAuthentication($criteria = null)
{
$uid_attr = "uid";
$mail_attr = "mail";
$name_attr = "cn";
$ldap_server = "ldap.bb.cc.dd";
$ldap_port = 389;
$base_dn = "ou=People,o=bb.cc.dd";
$timezone_offset = 1;
$authenticated = false;
if (isset($criteria) && is_subclass_of($criteria, 'criteriaelement')) {
$ds=ldap_connect($ldap_server, $ldap_port) or die("Could not connect to LDAP server.");
if($ds) {
//Authentication
$pass=$criteria->criteriaElements[1]->value; $ldapbind=ldap_bind($ds,$uid_attr."=".$criteria->criteriaElements[0]->value.",".$base_dn,$criteria->criteriaElements[1]->value);
if($ldapbind) {
$authenticated = true;
// Get info from LDAP (mail,name)
$sr=ldap_search($ds,$base_dn,$uid_attr."=".$criteria->criteriaElements[0]->value,Array($mail_attr,$name_attr));
$info = ldap_get_entries($ds, $sr);
if($info["count"] == 1) {
// Search user in the DB
$criteria = new CriteriaCompo(new Criteria('uname',$criteria->criteriaElements[0]->value));
$user =& $this->getObjects($criteria, false);
$member_handler =& xoops_gethandler('member');
if (!$user || count($user) != 1) {
$xuser =& $member_handler->createUser();
$xuser->setVar("uname",$criteria->criteriaElements[0]->value);
$xuser->setVar("user_avatar","blank.gif");
$xuser->setVar('user_regdate', time());
$xuser->setVar('timezone_offset', $timezone_offset);
$xuser->setVar('actkey',substr(md5(uniqid(mt_rand(), 1)), 0, 8));
}
else {
$xuser = & $user[0];
}
$xuser->setVar("email",$info[0][$mail_attr][0]);
$xuser->setVar("name",$info[0][$name_attr][0]);
$xuser->setVar("pass",md5($pass));
$xuser->setVar("level",1);
$xuser->setVar('notify_method', 2);
// Store info in DB (update or insert)
$ret = $this->insert($xuser);
//Add the user to Registered Users group
$member_handler->addUserToGroup(XOOPS_GROUP_USERS, $xuser->getVar('uid'));
}
}
ldap_close($ds);
}
else {
//echo "cannot connect to ldap server";
}
}
return $authenticated;
}
In order to minimize the files to modify I put all configuration data directly where there are used.
I suppose it should be located outside, but where ? (config.inc.php ?)
This hack should also work for those working with Active Directory (through LDAP, of course)
by simply adapting LDAP server info at the beginning of the LDAPAuthentication function.
Even if your LDAP server is down, registered users should be able to connect to Xoops.
I hope this will be useful for someone. In our case it allowed us to immediately adopt XOOPS for our internal developper portal.
Now I have to try the secure (SSL login page ?) authentication process to
avoid the "travelling" of clear passwords over the network... Any ideas or tips ?
Regards,
BM