Well here is my proof of concept code. In AD I setup two groups FOG_Admins and FOG_Users. The script outputs the following
false := user is not authorized
1 := User is authorized and is in the FOG_Users group
2 := User is authorized and is in the FOG_Admins group
I was going to go with the whole bindDN and bindPassword route, but that also meant that I would have to save the bindPass value in the database. To do that I would have to come up with a way to protect (encrypt) the password and all that. So I flipped the script around to use the person who is logging, their credentials to query AD.
The next steps here are to intergrate the script below into ldapAuth (which shouldn’t be hard at all) then update the database fields, and other creations bits. The last part will be to mess with the ldap gui interface which has me a bit confused on the layout.
But at the end of the day this is surely possible to get fog to authenticate against AD.
<?php
function ldapParseDn($dn) {
/**
* Returns array of: array (
* [CN] => array( username )
* [OU] => array( UNITNAME, Region, Country )
* [DC] => array ( subdomain, domain, com )
* )
**/
$parsr=ldap_explode_dn($dn, 0);
$out = array();
foreach($parsr as $key=>$value) {
if(FALSE !== strstr($value, '=')) {
list($prefix,$data) = explode("=",$value);
$prefix = strtoupper($prefix);
$data=preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $data);
if(isset($current_prefix) && $prefix == $current_prefix) {
$out[$prefix][] = $data;
} else {
$current_prefix = $prefix;
$out[$prefix][] = $data;
}
}
}
return $out;
}
$user = 'testuser';
$pass = 'testuser.1';
$server = '192.168.1.5';
// clean up user name we only want the user's short name without any domain component
// note I did not try to understand the regex expression but I expect there to be
// issues with non-us english characters, just saying.
$user = trim(preg_replace('/[^a-zA-Z0-9\-\_@\.]/', '', $user));
// open connection to the server
$ldapconn = ldap_connect($server,389);
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
$accessLevel = 0;
// test to confirm that script will handle mixed case
$userSearchDN = 'ou=nyc,dc=domain,DC=com';
$adminGroup = 'FOG_Admins';
$userGroup = 'FOG_Users';
// test to confirm that script will handle mixed case
$grpMemberAttr = strtolower('memberOf');
$entries = ldapParseDN($userSearchDN);
$userDomain = implode(".",$entries['DC']);
$userDN = sprintf('%s@%s', $user, $userDomain);
if ( ldap_bind($ldapconn, $userDN, $pass) ) {
// If we get to here the user is authorized, now lets get the group membership
$filter = sprintf('(&(objectCategory=person)(%s=%s))', 'sAMAccountName', $user);
$attr = array( $grpMemberAttr );
$result = ldap_search($ldapconn, $userSearchDN, $filter, $attr);
// count the number of entries returned
$retcount = ldap_count_entries($ldapconn, $result);
if ($retcount > 0) {
$entries = ldap_get_entries($ldapconn, $result);
// check groups for membership
foreach($entries[0][$grpMemberAttr] as $grps) {
// is admin user, set level and break loop
if(strpos( $grps, $adminGroup )) { $accessLevel = 2; break; }
// is user, set level and keep looking just incase user is in both groups
if(strpos( $grps, $userGroup )) $accessLevel = 1;
}
}
// close our connection as bindDN
ldap_unbind( $ldapconn );
print $accessLevel;
} else {
print 'unable to bind using user info, user is not authorized in ldap';
}
?>