<html>
<head>
<title>LDAP Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style>
BODY {
font-family: Verdana, Arial, Helvetica;
font-size: 12px;
}
P {
font-family: Verdana, Arial, Helvetica;
font-size: 12px;
}
</style>
</head>
<?
//Functions
//Parse UserAccountControl Flgs to more human understandable form...
function parseUACF($uacf) {
//All flags array
$flags = array( "TRUSTED_TO_AUTH_FOR_DELEGATION"=> 16777216,
"PASSWORD_EXPIRED" => 8388608,
"DONT_REQ_PREAUTH" => 4194304,
"USE_DES_KEY_ONLY" => 2097152,
"NOT_DELEGATED" => 1048576,
"TRUSTED_FOR_DELEGATION" => 524288,
"SMARTCARD_REQUIRED" => 262144,
"MNS_LOGON_ACCOUNT" => 131072,
"DONT_EXPIRE_PASSWORD" => 65536,
"SERVER_TRUST_ACCOUNT" => 8192,
"WORKSTATION_TRUST_ACCOUNT" => 4096,
"INTERDOMAIN_TRUST_ACCOUNT" => 2048,
"NORMAL_ACCOUNT" => 512,
"TEMP_DUPLICATE_ACCOUNT" => 256,
"ENCRYPTED_TEXT_PWD_ALLOWED" => 128,
"PASSWD_CANT_CHANGE" => 64,
"PASSWD_NOTREQD" => 32,
"LOCKOUT" => 16,
"HOMEDIR_REQUIRED" => 8,
"ACCOUNTDISABLE" => 2,
"SCRIPT" => 1);
//Parse flags to text
$retval = array();
while (list($flag, $val) = each($flags)) {
if ($uacf >= $val) {
$uacf -= $val;
$retval[] = $flag;
}
}
//Return human friendly flags
return($retval);
}
//parse SamAccountType value to text
function parseSAT($samtype) {
$stypes = array( 805306368 => "NORMAL_ACCOUNT",
805306369 => "WORKSTATION_TRUST",
805306370 => "INTERDOMAIN_TRUST",
268435456 => "SECURITY_GLOBAL_GROUP",
268435457 => "DISTRIBUTION_GROUP",
536870912 => "SECURITY_LOCAL_GROUP",
536870913 => "DISTRIBUTION_LOCAL_GROUP");
$retval = "";
while (list($sat, $val) = each($stypes)) {
if ($samtype == $sat) {
$retval = $val;
break;
}
}
if (empty($retval)) $retval = "UNKNOWN_TYPE_" . $samtype;
return($retval);
}
//Parse GroupType value to text
function parseGT($grouptype) {
$gtypes = array( -2147483643 => "SECURITY_BUILTIN_LOCAL_GROUP",
-2147483644 => "SECURITY_DOMAIN_LOCAL_GROUP",
-2147483646 => "SECURITY_GLOBAL_GROUP",
2 => "DISTRIBUTION_GLOBAL_GROUP",
4 => "DISTRIBUTION_DOMAIN_LOCAL_GROUP",
8 => "DISTRIBUTION_UNIVERSAL_GROUP");
$retval = "";
while (list($gt, $val) = each($gtypes)) {
if ($grouptype == $gt) {
$retval = $val;
break;
}
}
if (empty($retval)) $retval = "UNKNOWN_TYPE_" . $grouptype;
return($retval);
}
function getObjectSid($adConn, $dn, $distname) {
//Select which attributes wa want
$attrs = array("objectsid");
//Filter creation
$filter = "distinguishedname=" . addslashes($distname);
//Do the seacrh!
$search = ldap_search($adConn, $dn, $filter, $attrs) or die("**** happens, no connection!");
$entry = ldap_first_entry($adConn, $search);
$vals = ldap_get_values_len($adConn, $entry, "objectsid");
return(bin2hex($vals[0]));
}
if (empty($_GET["dn"])) $_GET["dn"] = "DC=sd1,DC=ad,DC=domain,DC=com";
if (empty($_GET["host"])) $_GET["host"] = "ldap://dc.sd1.ad.domain.com";
if (empty($_GET["user"])) $_GET["user"] = "username@sd1.ad.domain.com";
?>
<body>
<h3>AD Search with plain LDAP queries</h3>
<p>
<form method="GET">
<b>Search Criteria:</b><br>
<select name="filter">
<option value="cn"<? if ($_GET["filter"]=="cn") echo " selected"; ?>>cn</option>
<option value="sn"<? if ($_GET["filter"]=="sn") echo " selected"; ?>>sn</option>
<option value="userprincipalname"<? if ($_GET["filter"]=="userprincipalname") echo " selected"; ?>>userprincipalname</option>
<option value="samaccountname"<? if ($_GET["filter"]=="samaccountname" or empty($_GET["filter"])) echo " selected"; ?>>samaccountname</option>
<option value="telephonenumber"<? if ($_GET["filter"]=="telephonenumber") echo " selected"; ?>>telephonenumber</option>
<option value="l"<? if ($_GET["filter"]=="l") echo " selected"; ?>>City</option>
</select>
=
<input type="text" name="keyword" size="30" maxlength="100" value="<? echo $_GET["keyword"]; ?>" /><br>
<input type="checkbox" name="debugarray" id="debugarray" value="1"<? if ($_GET["debugarray"] == 1) echo " checked"; ?>><label for="debugarray">View debug array</label><br>
<input type="checkbox" name="test" id="test" value="1"<? if ($_GET["test"] == 1) echo " checked"; ?>><label for="test">Get results also with COM objects, it uses different ways than just an ldap, which is not good...</label><br>
<br>
DN = <input type="text" name="dn" size="50" maxlength="100" value="<? echo $_GET["dn"]; ?>" /><br>
host = <input type="text" name="host" size="50" maxlength="100" value="<? echo $_GET["host"]; ?>" /><br>
user/password = <input type="text" name="user" size="35" maxlength="100" value="<? echo $_GET["user"]; ?>" /> <input type="password" name="pass" size="10" maxlength="100" value="" /> If empty, defaults used.<br>
<br>
<br><input type="submit" value="Do the thing!">
</form>
</p>
<?php
//Connection parameters
$host = $_GET["host"];
if (empty($_GET["user"]) or empty($_GET["pass"])) {
$user = "default.user@sd1.ad.domain.com";
$pass = "default.password";
} else {
$user = $_GET["user"];
$pass = $_GET["pass"];
}
//Just a test with COM objects... Not very nice though!
if ($_GET["test"] == 1) {
$objConn = new COM("ADODB.Connection");
$objConn->Provider = "ADsDSOObject";
$objConn->Open("ADs Provider", $user, $pass);
$objRs = new COM("ADODB.Recordset");
$objCom = new COM("ADODB.Command");
$objCom->ActiveConnection = $objConn;
$objCom->CommandText = "SELECT objectsid,samAccountname,userAccountControl,userPrincipalName,ADsPath,givenName,sn,telephoneNumber,mail,displayName, department, distinguishedName FROM 'GC://dc=corp,dc=storaenso,dc=com' WHERE '" . $_GET["filter"] . "' = '" . $_GET["keyword"] . "'";
$objRs = $objCom->Execute;
echo "<p><b>COM object results:</b> " . $objRs->RecordCount . "</p>";
while (!$objRs->EOF) {
echo "<p>";
for ($i=0; $i < $objRs->Fields->Count; $i++) {
echo "$i: " . $objRs->Fields[$i]->value . "<br>\n";
}
$test = $objRs->Fields[11]->value;
echo "<b>ObjectSid:</b> " . $test . " (DEC?)";
echo "</p>";
$objRs->MoveNext();
}
} //end of test
//The real thing with PHP
if (!empty($_GET["keyword"]) and !empty($_GET["dn"])) {
//Connect to the AD
$adConn = ldap_connect($host, 636) or die("Could not connect!");
//Set protocol verison
ldap_set_option($adConn, LDAP_OPT_PROTOCOL_VERSION, 3) or die ("Could not set ldap protocol1");
//Set referrals... Won't work without this...
ldap_set_option($adConn, LDAP_OPT_REFERRALS, 0) or die ("Could not set ldap protocol2");
//Bind the user
$bd = ldap_bind($adConn, $user, $pass) or die ("Could not bind");
//Create DN
$dn = $_GET["dn"];
//Create the filter
$filter = $_GET['filter'] . "=" . $_GET["keyword"];
//Do the search
$search = ldap_search($adConn, $dn, utf8_encode($filter));
//Get results to an array
$entries = ldap_get_entries($adConn, $search);
//Free willy! Err... Result :-)
ldap_free_result($search);
//End binding
//ldap_unbind($adConn);
} else {
$entries = array();
}
echo "<p><b>Search filter:</b> " . $filter . "<br>";
echo "<b>Number of entries:</b> " . $entries["count"] . "</p>\n";
if ($entries["count"] > 0) {
//Print entries
for ($i = 0; $i < $entries["count"] ; $i++) {
echo "<hr>\n";
echo "<p><b>Entry:</b> " . ($i+1) . "<br>\n";
$SamAccountType = parseSAT(utf8_decode($entries[$i]["samaccounttype"][0]));
echo "<b>Sam-Account-Type:</b> " . $SamAccountType . "<br>\n";
if (ereg("GROUP", $SamAccountType)) echo "<b>Group-Type:</b> " . parseGT(utf8_decode($entries[$i]["grouptype"][0])) . "<br>\n";
echo implode("<br>\n", parseUACF(utf8_decode($entries[$i]["useraccountcontrol"][0]))) . "<br>\n";
if (utf8_decode($entries[$i]["pwdlastset"][0]) == 0 and utf8_decode($entries[$i]["pwdlastset"][0]) != "") echo "<b>User must change password at next logon</b><br>\n";
echo "<b>ObjectSid:</b> " . bin2hex($entries[$i]["objectsid"][0]) . " <font size=\"1\"><-Buggy method (HEX)</font><br>\n";
$objectsid = getObjectSid($adConn, $dn, $entries[$i]["distinguishedname"][0]);
echo "<b>ObjectSid:</b> " . $objectsid . " <font size=\"1\"><-Less buggy? (HEX) At least it seems to work and the data is somehow sensible.</font><br>\n";
echo "<b>ObjectSid lenght:</b> " . strlen($objectsid) . "<br>\n";
//echo "<b>ObjectSid:</b> " . getObjectSid($adConn, $entries[$i]["objectcategory"][0], $entries[$i]["distinguishedname"][0]) . "<br>\n";
echo "</p>";
// $ii = attributes for entry
// $iii = values per attribute
for ($ii=0; $ii<$entries[$i]["count"]; $ii++){
$data = $entries[$i][$ii];
for ($iii=0; $iii<$entries[$i][$data]["count"]; $iii++) {
echo "<b>" . utf8_decode($data) . ":</b> " . utf8_decode($entries[$i][$data][$iii]) . "<br>\n";
}
}
if ($_GET["debugarray"] == 1) {
echo "<pre>";
print_r($entries[$i]);
echo "</pre>";
}
}
} else {
echo "<p>No results found!</p>";
}
?>
</body>
</html>