Skip to content

Instantly share code, notes, and snippets.

@ZiTAL
Last active May 15, 2024 07:07
Show Gist options
  • Save ZiTAL/e5671ea15892688d58ad9b7024b5163e to your computer and use it in GitHub Desktop.
Save ZiTAL/e5671ea15892688d58ad9b7024b5163e to your computer and use it in GitHub Desktop.
php / laravel: ldap samaccountname
LDAP_DOMAIN="zital.lan"
LDAP_BASEDN="dc=zital,dc=lan"
LDAP_GROUPS='["Group01", "Group02"]'
LDAP_ATTRS='["*"]'
LDAP_HOSTS='["ldap01.zital.lan:389","ldap02.zital.lan:389","ldap02.zital.lan:389"]'
<?php
namespace App\Models;
class Ldap
{
private static $instance = NULL;
private static $options =
[
LDAP_OPT_PROTOCOL_VERSION => 3,
LDAP_OPT_REFERRALS => 0
];
// .env
private static $domain = '';
private static $basedn = '';
private static $attributes = [];
private static $groups = [];
private static $hosts = [];
public static function setDefaults()
{
self::$domain = env('LDAP_DOMAIN');
self::$basedn = env('LDAP_BASEDN');
self::$attributes = json_decode(env('LDAP_ATTRS'));
self::$groups = json_decode(env('LDAP_GROUPS'));
self::$hosts = json_decode(env('LDAP_HOSTS'));
}
public static function connect()
{
self::setDefaults();
$servers = self::$hosts;
$connection = false;
foreach ($servers as $server)
{
$ldap = ldap_connect("ldap://{$server}");
if ($ldap)
{
foreach (self::$options as $key => $value)
ldap_set_option($ldap, $key, $value);
if (ldap_bind($ldap))
{
$connection = true;
break;
}
}
}
if ($connection)
{
self::$instance = $ldap;
return true;
}
return false;
}
public static function getInstance()
{
if (!self::$instance)
self::connect();
return self::$instance;
}
public static function attempt($user, $passwd)
{
$instance = self::getInstance();
if ($instance)
{
if (@ldap_bind($instance, $user . "@" . self::$domain, $passwd))
{
$dns = self::getDN($user);
if (isset($dns, $dns['dn']) && self::checkGroup($instance, $dns['dn']))
return true;
}
}
return false;
}
public static function getDN($samaccountname)
{
$instance = self::getInstance();
$result = ldap_search($instance, self::$basedn, "(samaccountname={$samaccountname})", self::$attributes);
if ($result === FALSE)
return false;
$entries = ldap_get_entries($instance, $result);
if ($entries['count'] > 0)
return self::prepareEntry($entries[0]);
return false;
}
public static function checkGroup($ad, $userdn)
{
$attributes = ['memberof'];
$result = ldap_read($ad, $userdn, '(memberof=*)', $attributes);
if ($result === false)
return false;
$entries = ldap_get_entries($ad, $result);
if ($entries['count'] > 0 && isset($entries[0], $entries[0]['memberof'], $entries[0]['memberof']['count']))
{
$count = $entries[0]['memberof']['count'];
for ($i = 0; $i < $count; $i++)
{
$group = preg_match("/^CN=([^,]+)/", $entries[0]['memberof'][$i], $m);
if (isset($m) && isset($m[1]))
{
$group = $m[1];
if (in_array($group, self::$groups))
return true;
}
}
}
return false;
}
private static function prepareEntry($entry)
{
$result = [];
foreach ($entry as $key => $value)
{
$type = gettype($value);
if ($type === 'string' && isset($entry[$value]))
{
$key = $value;
$value = $entry[$value];
unset($value['count']);
if (count($value) === 1)
$value = $value[0];
}
// if is utf-8
if (preg_match('//u', serialize($value)))
$result[$key] = $value;
}
return $result;
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Session;
use App\Models\Ldap as LdapM;
class LdapC extends Controller
{
public function login(Request $request)
{
try
{
if(LdapM::attempt($request->user, $request->passwd))
{
$dn = LdapM::getDN($request->user);
Session::put('ldap', $dn);
return $dn;
}
else
return response()->json(['error' => 'Unauthorized'], 401);
}
catch(\Exception $e)
{
return response()->json(['error' => $e->getMessage()], 500);
}
}
public function logout(Request $request)
{
try
{
Session::flush();
}
catch(\Exception $e)
{
return response()->json(['error' => $e->getMessage()], 500);
}
}
public function get(Request $request)
{
try
{
$s = Session::get('ldap');
if($s)
return $s;
else
return response()->json(['error' => 'Unauthorized'], 401);
}
catch(\Exception $e)
{
return response()->json(['error' => $e->getMessage()], 500);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment