I'm establishing a connection to our Active Directory listing of users/employees. I've done this through .NET, but cant get it to work in my PHP app.
I consistantly get a count of 0.
I've tried using samaccountname and sAMaccountname as filters, this does not change the result.
I am successfully connecting, as changing the $ldap will no longer find the server.
I am using valid credentials, as changing $authUser or $authPath provide an authorized error message.
The ldap_bind (i presume) is working, because it does perform the search and outputs a count of 0.
Here is my code:
<?php
try{
$ldap = "vmc-dc.CompanyName.vmc";
$authUser = "vmc\\MyUsername";
$authPass = "MyPassword";
$baseDn = "dc=vmc-dc,dc=CompanyName,dc=com";
$filter="(&(objectClass=user)(samaccountname=*))";
$conn = ldap_connect($ldap, 389) ;
if ($conn) {
ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($conn, LDAP_OPT_REFERRALS, 0);
// binding to ldap server
$ldapbind = ldap_bind($conn, $authUser, $authPass);
// verify binding
if ($ldapbind) {
//$sr=ldap_read($conn, $baseDn, $filter);
$sr=ldap_search($conn, $baseDn, $filter);
$number_returned = ldap_count_entries($conn,$sr);
echo "Count: " . $number_returned . "<br/>";
$entry = ldap_get_entries($conn, $sr);
ldap_close($conn);
echo "value = '" . $entry[0] . "'";
} else {
echo "LDAP conn ok...";
}
}
} catch (Exception $e) {
}
?>
I wonder if your filter is too broad, all user class objects (which includes computers, to Brian Desmond's point) and is returning more than 1000 found objects. In which case AD will error, and return nothing. I would expect you would get a returned error, so this may not be likely. But a more constrained filter, and/or a repetition with a standalone LDAP tool could help validate this idea.
Related
I am integrating my login form with Microsoft active directory. I authenticate
users via LDAP php library.
When user try to log in, they enter username & password.
Connecting to server go successfully, authentication via "LDAP_bind" also
give me true or false according to the values correctness.
Now i am not able to retrieve the user Real name to display it on the screen.
ALL Information I have are the ldap uri with the port number, and username & password entered via the webform.
here is my current code,
$ldap = ldap_connect("ldap://abc.xyz:123");
if ($bind = ldap_bind($ldap, $_REQUEST['username'].'#abc.xyz',$_REQUEST['password']))
{ echo "Welcome". $_REQUEST['username'];}
the $_REQUEST['username'] is not human readable, so i need to read this user attributes or at least display name only.
ldap_search and ldap_read functions did not help, I tried this code:
$ldap_base_dn = 'DC=abc,DC=xyz';
$search_filter = "(objectclass=*)";
$result = ldap_search($ldap_connection, $ldap_base_dn, $search_filter);
with no luck, is there any other information i must have in order to make the ldap_search or ldap_read work successfully. in other words can this be done by having the username and password and the ldap uri only?
You should be able to do the search like this:
$upn = $_REQUEST['username'].'#abc.xyz';
$attributes = ['displayname'];
$filter = "(&(objectClass=user)(objectCategory=person)(userPrincipalName=".ldap_escape($upn, null, LDAP_ESCAPE_FILTER)."))";
$baseDn = "DC=abc,DC=xyz";
$results = ldap_search($ldap, $baseDn, $filter, $attributes);
$info = ldap_get_entries($ldap, $results);
// This is what you're looking for...
var_dump($info[0]['displayname'][0]);
Also, make sure to do the bind with these options:
$ldap = ldap_connect("ldap://abc.xyz:123");
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
if ($bind = ldap_bind($ldap, $_REQUEST['username'].'#abc.xyz',$_REQUEST['password']))
When returning the DisplayName value, I recommend that you use a search filter which looks for the samaccountname (username) using something as simple as (samaccountname=$u) with $u being the username from your LDAP connect. If your Active Directory/Open Directory has a lot of objects, I would most certainly recommend targeting OU's as this query can fall on it's bottom pretty quickly.
I've made some further changes to your code so it now runs inside a function which takes 3x params and returns false if the connection or authentication fails.
Check LDAP - Return DisplayName if success login or FALSE(BOOL) if fail login or connection.
function chkLDAP($u, $pass, $domain) {
$dom = "$domain\\"; //Domain Prefix for UNAME which ouputs "domain\"
$user = $dom . $u;
$hostname = 'ldap://abc.com';
$baseDN = 'OU=users, DC=abc, DC=com'; //Narrow down if you have alot of objects as search could take along time
$search = "(samaccountname=$u)"; //Compare with Username
$ldap = ldap_connect($hostname);
if ($ldap) {
$ldapbind = ldap_bind($ldap, $user, $pass);
if ($ldapbind) {
$ldapSearch = ldap_search($ldap, $baseDN, $search);
$entry = ldap_first_entry($ldap, $ldapSearch);
$info = ldap_get_values($ldap, $entry, "displayname");
return $info[0];
}
return false; //Failed Auth
}
return false; //Connection Failed
}
Just test the function for false to make sure you have a displayname before using it.
Run Function:
$displayName = chkLDAP($_REQUEST['username'], $_REQUEST['password'], 'abc.com'); //Run Function - Returns False if Failed or Displayname if True
if ($displayName !== false) {
echo $displayName;
} else {
echo "Username or Password Incorrect!";
}
See:
http://php.net/manual/en/function.ldap-get-values.php
This worked for me for people who need to validate if a user exists in a specific OU.
(by the help of #kitson88 response)
function validateLogin($username,$password)
{
$ldap_dn = "$username#alhait.com";
$ldap_password =$password;
$ldap_con = ldap_connect("server");
ldap_set_option($ldap_con, LDAP_OPT_PROTOCOL_VERSION, 3);
if(#ldap_bind($ldap_con,$ldap_dn,$ldap_password))
{
$baseDN = 'OU=trainers,DC=alhait,DC=com';
$search = "(samaccountname=$username)";
$ldapSearch = ldap_search($ldap_con, $baseDN, $search);
$entry = ldap_first_entry($ldap_con, $ldapSearch);
$info = ldap_get_values($ldap_con, $entry, "displayname");
// var_dump($info[0]);
if($info[0]!=null)
{
return true;
}
}else{
return false;
}
//echo "Invalid Credential";
return false;
}
I'm trying for the first time to use LDAP in some PHP code. I want to determine if someone is a member of a particular AD group.
I've cobbled together some code from other examples and this runs without error, but indicates 0 results, when the user is in fact a member of the group.
Here is my code:
$hostname="192.168.1.1";
$conn=ldap_connect($hostname, 389);
ldap_set_option ($conn, LDAP_OPT_REFERRALS, 0) or die('Unable to set LDAP opt referrals');
ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3) or die('Unable to set LDAP protocol version');
if ($conn) {
$dn = "DC=domain,DC=local";
// if (!($ldapc=ldap_bind($conn,'CN=Username,CN=Users,DC=domain,DC=local','P#ssw0rd'))) {
if (!($ldapc=ldap_bind($conn,'username#domain.local','N0tMyP#ssw0rd'))) {
Is the full CN=,DC=, etc or the #domain.local the preferred method here?
Also, I am assuming that all searches performed for membership will be against the user authenticated by the ldap_bind()?
code continues:
echo "<p>Error:" . ldap_error($conn) . "</p>";
echo "<p>Error number:" . ldap_errno($conn) . "</p>";
echo "<p>Error:" . ldap_err2str(ldap_errno($conn)) . "</p>";
die;
}
$attributes = array("memberOf");
$filter = "(memberOf=myGroup,OU=Application Security,DC=domain,DC=local)";
$result = ldap_search($conn, $dn, $filter, $attributes);
echo $result."<BR />";
$info = ldap_get_entries($conn, $result);
echo $info["count"]." entries returned.\n";
for ($i=0; $i < $info["count"]; $i++) {
echo $info[$i]["ou"][0];
}
} else {
echo "<h4>Unable to connect to LDAP server</h4>";
}
ldap_unbind($conn);
EDIT:
After suggestions below, I was able to get this working as expected. Here is the final working code for those who would benefit...
$hostname="192.168.1.1";
$conn=ldap_connect($hostname, 389);
ldap_set_option ($conn, LDAP_OPT_REFERRALS, 0) or die('Unable to set LDAP opt referrals');
ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3) or die('Unable to set LDAP protocol version');
if ($conn) {
$dn = "DC=domain,DC=local";
if (!($ldapc=ldap_bind($conn,'CN=Administrator,CN=Users,DC=domain,DC=local','password'))) {
echo "<p>Error:" . ldap_error($conn) . "</p>";
echo "<p>Error number:" . ldap_errno($conn) . "</p>";
echo "<p>Error:" . ldap_err2str(ldap_errno($conn)) . "</p>";
die;
}
$filter = "(memberOf=cn=Dashboard,OU=Application Security,DC=domain,DC=LOCAL)";
$result = ldap_search($conn, $dn, $filter);
// $attributes = array('samaccountname');
//$result = ldap_search($conn, $dn, $filter, $attributes);
$info = ldap_get_entries($conn, $result);
echo $info["count"]." entries returned.<br />";
for ($i=0; $i < $info["count"]; $i++) {
echo $i . " " . $info[$i]["samaccountname"][0] . "<br />";
}
} else {
echo "<h4>Unable to connect to LDAP server</h4>";
}
ldap_unbind($conn);
Personally I prefer the cn=... way to bind to a directory as it's universal. The username#domain-version only works on AD.
And the user that binds to the directory is NOT the user you are looking up the groups for but the user you are looking up the information with.
So when the user you are binding to the LDAP-Server with doesn't have the right to see the group information you won't have much luck. On the other hand if you'd need to login with the user you are looking the group-memberships for you could only retrieve the group-memberships when you know the password of the user. Taht would be a bit strange, wouldn't it?
And as the user binding to the LDAP-Server only has to have read-permission to the LDAP-Server often it is possible to use an anonymous bind without the need for a real user to bind. You would then simply omit the user and password-fields on the ldap_bind. But that depends on the setup of the Server.
To get the number of results returned by your query you can also use the ldap_count_entries($connectionHandle, $resultHandle)-function but I assume that there is an issue in your search-filter.
The search-filter has to contain a query. In your case you just give a string but you don't tell the LDAP-Server wwhich field to map it against. The filter always looks something ike this: <fieldname>=<querystring>. So in your case that would be memberOf=cn=mygroup,OU=Application Security,DC=domain,DC=local. The difference being that the group is identified by it's complete DN which (I assume here) is cn=mygroup,OU=Application Security,DC=domain,DC=local - You'll have to verify that!
The query will return you all users that are a member of that role. And it will only return you the memberOf-Attribute of those users which you know already. So you should either leave the $attributes empty or use something like ['cn', 'sAMAcountName', 'mail'] to get the CN, the Users ID and the email-address returned.
In a second step you will then have to check whether the user you are looking for actually is in that returned array.
Alternatively you could just search vor the user (filter would be something like mail=<email-address> or sAMAcountName=<user-ID> and get the memberOf value returned. you will then have to look whether the required group is one of the ones in the memberOf-Entry.
Scared? Didn't understand it? Don't worry. Ask!
I'm trying to list my Active Directory users using PHP ldap_list() function. I get the following errors when I execute the php code.
LDAP bind successful... Warning: ldap_list(): Search: Bad search filter in /var/www/html/ldapn.php on line 29
Below is my PHP Code:
<?php
// using ldap bind
$ldaprdn = 'draven#myserver.com'; // ldap rdn or dn
$ldappass = 'draven678'; // associated password
// connect to ldap server
$ldapconn = ldap_connect("dc.myserver.com")
or die("Could not connect to LDAP server.");
if ($ldapconn) {
// binding to ldap server
$ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);
// verify binding
if ($ldapbind) {
echo "LDAP bind successful...";
} else {
echo "LDAP bind failed...";
}
$basedn = "dc=myserver, dc=com";
$justthese = array("OU_Test");
$sr = ldap_list($ldapconn, $basedn, "OU_Test=*", $justthese);
}
?>
note : OU_Test is an Organizational unit. My requirement is to list all users in that Organizational Unit.
What's wrong with my code? How will I be able to resolve this error?
To list all users in the Organizational Unit 'OU_TEST' with ldap_list() :
Use the appropriate $basedn. It should be the distinguished name of 'OU_TEST' since you want to list users that are INSIDE OU_TEST. You can get it with ldap_search().
Use the appropriate filter : to list only users, filter by users.
// 1. Get OU_TEST's dn. Search down the tree using a top/root dn as $basedn :
$basedn = "dc=myserver, dc=com";
// Filters usually looks like ([attributeName]=[attributeValue])
$filter = '(ou=OU_TEST)';
$sr = ldap_search($ds, $basedn, $filter);
... say we put the resulting dn in $OU_TEST_dn variable...
// 2. List users. If users are missing, use 'objectClass=organizationalPerson'
$filter = '(objectClass=Users)';
// Use the correct basedn
$basedn = $OU_TEST_dn;
// This should work
$sr = ldap_list($ldapconn, $basedn, $filter);
the filter here should be in braces:
here is how:
$sr = ldap_list($ldapconn, $basedn, "(OU_Test=*)", $justthese);
This should work just fine.
If it doesn't work
follow the example here
<?php
$ldapconfig['host'] = '10.10.10.10';
$ldapconfig['port'] = NULL;
$ldapconfig['basedn'] = 'dc=company,dc=com';
$ds=ldap_connect($ldapconfig['host'], $ldapconfig['port']);
$dn="uid=".$username.",ou=OU_TEST,".$ldapconfig['basedn'];
if ($bind=ldap_bind($ds, $dn, $password)) {
echo("Login correct");
} else {
echo("Unable to bind to server.</br>");
echo("msg:'".ldap_error($ds)."'</br>"); //check if the message isn't: Can't contact LDAP server :)
//if it say something about a cn or user then you are trying with the wrong $dn pattern i found this by looking at OpenLDAP source code :)
//we can figure out the right pattern by searching the user tree
//remember to turn on the anonymous search on the ldap server
if ($bind=ldap_bind($ds)) {
$filter = "(OU_TEST=*)";
if (!($search=#ldap_search($ds, $ldapconfig['basedn'], $filter))) {
echo("Unable to search ldap server<br>");
echo("msg:'".ldap_error($ds)."'</br>"); //check the message again
} else {
$number_returned = ldap_count_entries($ds,$search);
$info = ldap_get_entries($ds, $search);
echo "The number of entries returned is ". $number_returned."<p>";
for ($i=0; $i<$info["count"]; $i++) {
var_dump($info[$i]); //look for your user account in this pile of junk and apply the whole pattern where you build $dn to match exactly the ldap tree entry
}
}
} else {
echo("Unable to bind anonymously<br>");
echo("msg:".ldap_error($ds)."<br>");
}
}
?>
Let me know if it does not work. We will try and figure it out!
I have tried adding users via php ldap Active-Directory for Microsoft Server 2008 R2 datacenter, but I can't. I always get this error :
An error occurred. Error number 64: Naming violation
The code is:
<?php
$ldaprdn = 'administrador#correo.mx';
$ldappass = 'dir378prob#';
$ds = 'correo.mx';
$dn = 'ou=usuarios,dc=correo,dc=mx';
$puertoldap = 389;
$ldapconn = ldap_connect($ds,$puertoldap)or die("ERROR: I Don'n connect to LDAP.");
if ($ldapconn)
{
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION,3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS,0);
$con = ldap_bind($ldapconn, $ldaprdn, $ldappass);
if ($con)
{
$info["cn"] = $_POST['cn'];
$info["sn"] = $_POST['sn'];
$info["mail"] = $_POST['mail'];
$info["objectclass"] = "inetorgperson";
// prepare DN for new entry
$dn_aux = "mail=" . $_POST['mail'] . ",ou=usuarios,dc=correo,dc=mx";
$result = ldap_add($ldapconn, $dn_aux, $info);
if($result)
{
echo "New entry with DN " . $dn . " added to LDAP directory.";
}
// else display error
else
{
echo "An error occurred. Error number " . ldap_errno($conn) . ": " .
ldap_err2str(ldap_errno($conn));
}
}
else
{
echo "LDAP bind error...";
}
}
ldap_close($ldapconn);
?>
I'm taking my first steps in this ldap, so please could you explain in detail.
Not sure of the correct PHP syntax but the following line :
$dn_aux = "mail=" . $_POST['mail'] . ",ou=usuarios,dc=correo,dc=mx";
is not correct concerning an Active-Directory. The explanation is that in such a Directory your are not able to choose the attribute you use for naming an object. For example an 'InetOrgPerson' object MUST use the CN attribute to name it. For more details read carefuly naming attributes in object naming from Microsoft documentation.
try :
dn_aux = "CN=" . $_POST['cn'] . ",ou=usuarios,dc=correo,dc=mx";
I am wanting to create a form that I can fill out and once I submit it the form values can be pulled out and that person can be created into LDAP. I am not very experienced with LDAP infact I just worked towards making an LDAP bind work so I am needing some help. How can I add new users into LDAP through this form I can fill out? I know LDAP has an Add commands but I am not particularly sure on how to get started and what information needs to be passed for the person to be created in LDAP. If it helps, below is my code for LDAP bind.
<?php
$name=$_REQUEST['name'];
$x=1;
if($x==1)
{
//LDAP stuff here.
$username = "myusername";
$password = "mypass";
$ds = ldap_connect('ldap://ldap:389');
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
//Can't connect to LDAP.
if( !ds )
{
echo "Error in contacting the LDAP server -- contact ";
echo "technical services! (Debug 1)";
exit;
}
//Connection made -- bind anonymously and get dn for username.
$bind = #ldap_bind($ds);
//Check to make sure we're bound.
if( !bind )
{
echo "Anonymous bind to LDAP FAILED. Contact Tech Services! (Debug 2)";
exit;
}
$search = ldap_search($ds, "ou=People,DC=sde,DC=goliat,DC=com", "uid=$username");
//Make sure only ONE result was returned -- if not, they might've thrown a * into the username. Bad user!
if( ldap_count_entries($ds,$search) != 1 )
{
echo "Error processing username -- please try to login again. (Debug 3)";
redirect(_WEBROOT_ . "/try1b.php");
exit;
}
$info = ldap_get_entries($ds, $search);
//Now, try to rebind with their full dn and password.
$bind = #ldap_bind($ds, $info[0][dn], $password);
if( !$bind || !isset($bind))
{
echo "Login failed -- please try again. (Debug 4)";
redirect(_WEBROOT_ . "/try1b.php");
exit;
}
//Now verify the previous search using their credentials.
$search = ldap_search($ds, "ou=People,DC=sde,DC=goliat,DC=com", "cn=$name");
$info = ldap_get_entries($ds, $search);
if( $username == "myusername" )
{
/*
very useful set of information to view the LDAP tree info from an array
echo $username;
echo "<pre>".print_r($info[0],true)."</pre><br />";
*/
echo $info[0][cn][0];
echo ",";
echo $info[0][mail][0];
echo ",";
echo $info[0][telephonenumber][0];
exit;
}
else
{
echo "Error. Access Denied";
redirect(_WEBROOT_ . "/try1b.php");
exit;
}
ldap_close($ds);
exit;
}
?>
I would recommend a newUser.php (or whatever) file that checks to make sure that all of your required information is present, then send that info to the file you have started above.
Your $bind should take three variables...
$bind = ldap_bind($ds, 'cn=root,dc=example,dc=com', secretPassword);
For a pretty good guide to adding people to your LDAP server via PHP go to http://www.php2python.com/wiki/function.ldap-add/
Good luck
An add request requires the distinguished name to be added and the attribute that are to be part of the entry, and optional request controls.
On another subject, your search has subtree scope and may return more than one entry that matches user name. There is no reason why there could not be multiple entries with the same RDN in different branches underneath the base object specified in the code - unless your directory server vendor has implemented an attribute uniqueness constraint.