Something I made for my company as a modification and decided to release it.
save as include/class.ldap.php
class LDAP {
static function ldapConnect() {
require_once('../main.inc.php');
require_once(INCLUDE_DIR . 'ldap-config.php');
foreach (unserialize(LDAP_CONTROLLERS) as $controller) {
$ldap = ldap_connect($controller, LDAP_PORT);
if ($ldap) {
break;
}
}
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
return $ldap ? $ldap : false;
}
public static function ldapAuthenticate($username, $password) {
$ldap = LDAP:();
$bind = ldap_bind($ldap, $username . LDAP_SUFFIX, $password);
ldap_unbind($ldap);
return $bind;
}
public static function ldapScan(&$errors) {
$ldap = LDAP:();
if ($ldap) {
require_once(INCLUDE_DIR . 'class.staff.php');
$bind = ldap_bind($ldap, LDAP_ADMIN_USER . LDAP_SUFFIX, LDAP_ADMIN_PASS);
if ($bind) {
$ldap_f = unserialize(LDAP_FIELDS);
$ost_f = unserialize(OST_FIELDS);
$results = ldap_search($ldap, LDAP_BASE_DN, "(&(objectClass=user)(memberof=" . LDAP_GROUP_CN . LDAP_BASE_DN . "))", $ldap_f);
$info = ldap_get_entries($ldap, $results);
unset($info);
foreach ($info as $mem) {
for ($i = 0; $i < count($ldap_f); $i++) {
$user[$ost_f = $mem[$ldap_f;
}
$users = $user;
}
foreach ($users as &$u) {
$u = array_merge($u, unserialize(DEFAULT_FIELDS));
if (!Staff:($u, $error)) {
if($error=='Username already in-use'){
$error = array();
}
if(!empty($error)){
$errors[$u = $error;
}
}
$error = array();
}
ldap_unbind($ldap);
} else{
$errors = 'Cannot authenticate with LDAP server.';
}
} else{
$errors = 'Cannot connect to LDAP server.';
}
return $errors ? false : true;
}
}
save as include/ldap-config.php
define('LDAP_BASE_DN','DC=example,DC=com'); //Base DN used to search
define('LDAP_SUFFIX','@example.com'); //Appended to users to make things work
define('LDAP_CONTROLLERS',serialize(array('ldap.example.com'))); //Domain controller
define('LDAP_GROUP_CN','CN=OST,OU=Groups'); //This is the group that is automatically added with scan and add and used for authentication
define('LDAP_ADMIN_USER','ADMIN'); //Used for querying data
define('LDAP_ADMIN_PASS','PASSWORD'); //Used for querying data
define('LDAP_FIELDS',serialize(array('samaccountname', 'givenname', 'sn', 'mail', 'telephonenumber'))); //These two fields, this one is for how your directory stores
define('OST_FIELDS',serialize(array('username', 'firstname', 'lastname', 'email', 'phone'))); //Must be parallel, this one is the related field for OS Ticket, required fields are already here
define('DEFAULT_FIELDS',serialize(array('npassword'=>'changethis','vpassword'=>'changethis','group_id'=>'0','dept_id'=>'0','isactive'=>'1'))); //Default values that aren't queried for using LDAP, like group, status, etc. Input these based on need.
define('LDAP_PORT','389'); //389 is default for LDAP, 636 is default for LDAPS
Three functions:
ldapScan: Probes an AD group for users to be added. It takes an array parameter similar to the staff class's save function, except it will also return arrays within it corresponding to each user who was unable to be added (with the exception of users who were unable to be added because they already exist). For example: If a user with the username "Foo.Bar." had an invald e-mail, it'd return an array such as
Array( => Array( => Valid email required))
ldapAuthenticate: Attempts to bind (authenticate) to your Active Directory. It does NOT check membership of a specific group, it only sees if it's a valid user in your Active Directory.
ldapConnect: An internal function used to connect to LDAP in either function.
One method of implementation for ldapScan:
In scp/admin.php:
After:
$nav->addSubMenu(array('desc'=>'Staff Members','href'=>'admin.php?t=staff','iconclass'=>'users'));
$nav->addSubMenu(array('desc'=>'Add New User','href'=>'admin.php?t=staff&a=new','iconclass'=>'newuser'));
$nav->addSubMenu(array('desc'=>'User Groups','href'=>'admin.php?t=groups','iconclass'=>'groups'));
$nav->addSubMenu(array('desc'=>'Add New Group','href'=>'admin.php?t=groups&a=new','iconclass'=>'newgroup'));
Add:
$nav->addSubMenu(array('desc'=>'Scan For and Add New AD Users','href'=>'admin.php?t=scan','iconclass'=>'ldap')); //ldap module
This will create a nice little button above the staff directory in the admin panel.
After:
case 'staff':
$page='staffmembers.inc.php';
if(($id=$_REQUEST?$_REQUEST:$_POST) && is_numeric($id)) {
$staff = new Staff($id);
if(!$staff || !is_object($staff) || $staff->getId()!=$id) {
$staff=null;
$errors='Unable to fetch info on rep ID#'.$id;
}
}
$page=($staff or ($_REQUEST=='new' && !$uID))?'staff.inc.php':'staffmembers.inc.php';
break;
Add:
//begin LDAP module
case 'scan':
require_once(INCLUDE_DIR.'class.ldap.php');
LDAP:($errors);
$page='staffmembers.inc.php';
break;
//end LDAP module
In scp/css/main.css:
After:
#nav a.users { background(../images/icons/list_users.gif) 0 5px no-repeat #ececec; }
#nav a.newuser { background(../images/icons/new_user.gif) 0 5px no-repeat #ececec; }
#nav a.groups { background(../images/icons/list_groups.gif) 0 5px no-repeat #ececec; }
#nav a.newgroup { background(../images/icons/new_group.gif) 0 5px no-repeat #ececec; }
Add:
#nav a.ldap { background(../images/icons/ldap_scan.gif) 0 5px no-repeat #ececec; } /*ldap module*
Finally add an image (named scp/images/icons/ldap_scan.gif), here's a quick one I made: and place it in the scp/images/icons folder.
Now you should be able to add users from your an AD group of your choosing from the admin panel!
Quick LDAP Authentication Implementation
In scp/login.php:
After:
require_once(INCLUDE_DIR.'class.staff.php');
Add:
require_once(INCLUDE_DIR.'class.ldap.php');
Change:
if(!$errors && ($user=new StaffSession($_POST)) && $user->getId() && $user->check_passwd($_POST)){
To:
if(!$errors && ($user=new StaffSession($_POST)) && $user->getId() && /*$user->check_passwd($_POST)*/ LDAP:($_POST, $_POST)){
(commented code kept in case you want to revert)
All questions, comment, concerns, and points of improvement are welcome! :