Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

osTicket v1.10 (stable) and Maintenance Release v1.9.15 are now available! Go get it now

Active Directory User Addition / Authentication

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::ldapConnect();
$bind = ldap_bind($ldap, $username . LDAP_SUFFIX, $password);
ldap_unbind($ldap);
return $bind;
}

public static function ldapScan(&$errors) {
$ldap = LDAP::ldapConnect();
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['count']);
foreach ($info as $mem) {
for ($i = 0; $i < count($ldap_f); $i++) {
$user[$ost_f[$i]] = $mem[$ldap_f[$i]][0];
}
$users[] = $user;
}
foreach ($users as &$u) {
$u = array_merge($u, unserialize(DEFAULT_FIELDS));
if (!Staff::create($u, $error)) {
if($error['username']=='Username already in-use'){
$error = array();
}
if(!empty($error)){
$errors[$u['username']] = $error;
}
}
$error = array();
}
ldap_unbind($ldap);
} else{
$errors['authentication'] = 'Cannot authenticate with LDAP server.';
}
} else{
$errors['connection'] = '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(['Foo.Bar'] => Array(['email'] => 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['id']?$_REQUEST['id']:$_POST['staff_id']) && is_numeric($id)) {
$staff = new Staff($id);
if(!$staff || !is_object($staff) || $staff->getId()!=$id) {
$staff=null;
$errors['err']='Unable to fetch info on rep ID#'.$id;
}
}
$page=($staff or ($_REQUEST['a']=='new' && !$uID))?'staff.inc.php':'staffmembers.inc.php';
break;

Add:
//begin LDAP module
case 'scan':
require_once(INCLUDE_DIR.'class.ldap.php');
LDAP::ldapScan($errors);
$page='staffmembers.inc.php';
break;
//end LDAP module


In scp/css/main.css:
After:
#nav a.users { background:url(../images/icons/list_users.gif) 0 5px no-repeat #ececec; }
#nav a.newuser { background:url(../images/icons/new_user.gif) 0 5px no-repeat #ececec; }
#nav a.groups { background:url(../images/icons/list_groups.gif) 0 5px no-repeat #ececec; }
#nav a.newgroup { background:url(../images/icons/new_group.gif) 0 5px no-repeat #ececec; }


Add:
#nav a.ldap { background:url(../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: image 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['username'])) && $user->getId() && $user->check_passwd($_POST['passwd'])){


To:
if(!$errors && ($user=new StaffSession($_POST['username'])) && $user->getId() && /*$user->check_passwd($_POST['passwd'])*/ LDAP::ldapAuthenticate($_POST['username'], $_POST['passwd'])){

(commented code kept in case you want to revert)

All questions, comment, concerns, and points of improvement are welcome! :cool:

Comments

  • Apologies for my question as I have not installed this MOD yet. Does this MOD automate the addition of only 'Staff' or does this look for new 'Customers' or 'Employees' to link to authenticate to OSticket?


    Rich
  • In ldap-config.php changethis ???

    save as include/ldap-config.php

    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.

    UR post is very usefull to me ... but i cant find wht need to go into place call changethis ???? any help
  • Thanks!!!!!!!!!!!!!!!!!!!!!!!!!
  • Thanks for posting this code. Now, I would need this to work with OpenLdap to make my day :)

    Has anybody modified this for OpenLdap and care to share the know-how?
  • It's don't work :(
    /var/log/httpd/error_log
    [Thu Jan 17 13:40:01 2013] [error] [client 192.168.213.220] PHP Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Moscow' for 'MSK/4.0/no DST' instead in /var/www/html/support/include/class.config.php on line 73
    [Thu Jan 17 13:40:02 2013] [error] [client 192.168.213.220] File does not exist: /var/www/html/images, referer: http://10.128.1.189/support/scp/
    [Thu Jan 17 14:04:36 2013] [error] [client 192.168.212.213] Directory index forbidden by Options directive: /var/www/html/
    [Thu Jan 17 14:04:36 2013] [error] [client 192.168.212.213] File does not exist: /var/www/html/favicon.ico

    In Brouser I see http://10.128.1.189/support/scp/ :
    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::ldapConnect(); $bind = ldap_bind($ldap, $username . LDAP_SUFFIX, $password); ldap_unbind($ldap); return $bind; } public static function ldapScan(&$errors) { $ldap = LDAP::ldapConnect(); 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['count']); foreach ($info as $mem) { for ($i = 0; $i < count($ldap_f); $i++) { $user[$ost_f[$i]] = $mem[$ldap_f[$i]][0]; } $users[] = $user; } foreach ($users as &$u) { $u = array_merge($u, unserialize(DEFAULT_FIELDS)); if (!Staff::create($u, $error)) { if($error['username']=='Username already in-use'){ $error = array(); } if(!empty($error)){ $errors[$u['username']] = $error; } } $error = array(); } ldap_unbind($ldap); } else{ $errors['authentication'] = 'Cannot authenticate with LDAP server.'; } } else{ $errors['connection'] = 'Cannot connect to LDAP server.'; } return $errors ? false : true; }

    in /var/www/html/support/include/class.config.php on line 73:

    function setMysqlTZ($tz){
    //TODO: Combine the 2 replace regex
    $this->mysqltzoffset=($tz=='SYSTEM')?preg_replace('/([+-]\d{2})(\d{2})/','\1',date('O')):preg_replace('/([+-]\d{2})(:)(\d{2})/','\1',$tz);
    }
  • It looks to me like include/class.ldap.php should have:
    <?php </div>
    at the beginning of the file.
    ?>
    at the end of the file.
  • ntozier;33670 said:
    It looks to me like include/class.ldap.php should have:

    at the beginning of the file.

    at the end of the file.
    After this change I have this error log:
    /var/log/httpd/error_log :
    [Fri Jan 18 14:23:28 2013] [error] [client 192.168.213.220] PHP Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Moscow' for 'MSK/4.0/no DST' instead in /var/www/html/support/include/class.config.php on line 73, referer: http://10.128.1.189/support/scp/
    [Fri Jan 18 14:23:28 2013] [error] [client 192.168.213.220] PHP Parse error: syntax error, unexpected ';', expecting T_FUNCTION in /var/www/html/support/include/class.ldap.php on line 63, referer: http://10.128.1.189/support/scp/

    include/class.ldap.php on line 63 :
    ?>

    Have you working scripts? Can I copy it, with my change?
Sign In or Register to comment.