When creating the user I cannot start the section with the user's password. The user is created, but when testing the connection, it marks invalid credentials. Can you tell me where I am wrong? How should the password be encrypted?
$ds = '192.168.1.10';
$portldap = 389;
$ldap_username = 'CN=Administrador,CN=Users,DC=Local,DC=com';
$ldap_password = 'rootadm1';
$ldap_password_user = $ldap_password;
$ldap_connection = ldap_connect($ds, $portldap);
if($ldap_connection ){
// We have to set this option for the version of Active Directory we are using.
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3) or die('Unable to set LDAP protocol version');
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, 0); // We need this for doing an LDAP search.
$r = ldap_bind($ldap_connection, $ldap_username, $ldap_password);
if($r === TRUE){
$CN = htmlspecialchars($_POST["cn"]);
$ldaprecord['cn'] = $CN;
$ldaprecord['sAMAccountName'] = $_POST["sAMAccountName"]; //20caract
$ldaprecord['userPrincipalName'] = $_POST["userprincipalname"];
$ldaprecord["objectClass"][0] = "top";
$ldaprecord["objectClass"][1] = "person";
$ldaprecord["objectClass"][2] = "organizationalPerson";
$ldaprecord["objectClass"][3] = "user";
$ldaprecord['description']= $_POST["description"];
$ldaprecord["userAccountControl"][0] = "66656";
$ldap_new = 'CN='.$CN.',CN=Users,DC=Local,DC=com';
$result = ldap_add($ldap_connection, $ldap_new, $ldaprecord);
if($result) {
//Success creating user - Add password
$addPrecord['userPassword'] = '{MD5}' . base64_encode(pack('H*',md5($ldap_password_user)));
//$addPrecord["unicodePwd"][0] = iconv( 'UTF-8', 'UTF-16LE', $ldap_password_user );
$add_record= ldap_modify($ldap_connection, $ldap_new, $addPrecord);
if($add_record){
ldap_close($ldap_connection);
return $result;
}
else {
echo "LDAP Error: ".ldap_error($ldap_connection)."\n";
exit;
}
}
else {
echo "LDAP Error: ".ldap_error($ldap_connection)."\n";
exit;
}
}
}
else {
echo "cannot connect to LDAP server at $ds.";
} ```
[enter image description here][1]
[1]: https://i.stack.imgur.com/QOzqZ.png
i try to add a user to freeipa with the code below. the code return success but when i go to the freeipa UI the user is not visible. if i try to reinsert it will fail telling that user already exist. what can be? thanks
$con = ldap_connect($server);
ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
// bind anon and find user by uid
$user_search = ldap_search($con,$dn,"(|(uid=admin))");
$user_get = ldap_get_entries($con, $user_search);
$user_entry = ldap_first_entry($con, $user_search);
$user_next = ldap_next_entry($con, $user_entry);
$user_dn = ldap_get_dn($con, $user_next);
if (ldap_bind($con, $user_dn, "adminpass") === false) {
$message[] = "Error E101 - Current Username or Password is wrong.";
}else{
$info['givenName'] = "test";
$info['cn'] = "test";
$info['sn'] = "user";
$info['mail'] = "test#localhost";
$info['objectclass'][0] = "inetorgperson";
if(ldap_add($con, "cn=test,cn=users,cn=accounts,dc=domain,dc=net", $info) === false){
$error = ldap_error($con);
$errno = ldap_errno($con);
$message[] = "$errno - $error";
}else{
$message[] = "ok";
}
}
I'm working with Symfony 2.8.2, Doctrine.
I need to create users in my app data base, but first I need to check if those users exist on a external Active Directory database. Only if the user exist it will possible to create the user on the app data base. My code works for creat users, but now I'm trying to implementate the "check if the user exist first" section, I'm following some examples but I'm not sure if the way I'm doing it goes well. I've read that the usual sequence with LDAP is connect, bind, search, interpret search result, close connection. Could someone give me a hint on what should I do with my code, where should I do the search first, before or after the bind? and why.
public function createAction(Request $request){
$em = $this->getDoctrine()->getManager();
$post_send = $request->request->get('userbundle_user');
if (array_key_exists('id', $post_send)) {
$ldap_success = true;
$entity = $em->getRepository('UserBundle:User')->find($post_send['id']);
}else{
$ldapconn = ldap_connect("10.0.0.230");
$Pass= "XXXXXX";
$searchUser = "YYYYYY";
$ldap_success = false;
if (#ldap_bind($ldapconn, $searchUser, $Pass)) {
try{
$post_send['password'] = $Pass;
$attributes = ['cn'];
$filter = "(&(objectClass=user)(objectCategory=person)(userPrincipalName=".ldap_escape($post_send['username'], null, LDAP_ESCAPE_FILTER)."))";
$baseDn = "DC=XXX,DC=XX,DC=cl";
$results = #ldap_search($ldapconn, $baseDn, $filter);
//$info = #ldap_get_entries($ldapconn, $results);
if ( $results ) {
$ldap_success = true;
} else {
$ldap_success = false;//false, lo deje en true para que pudiera avanzar
}
}
catch(\Exception $e){
$ldap_success = false;
}
}
$entity = new User();
}
if( $ldap_success ){
$entity->setUsername($post_send['username']);
$entity->setRut($post_send['rut']);
//$entity->setSalt("ssss");
if (array_key_exists('password', $post_send)) {
if ( $post_send['password'] != "" ) {
$entity->setPassword($post_send['password']);
$this->setSecurePassword($entity);
}
}
$entity->setEmail($post_send['email']);
$entity->setDateAdded(new \DateTime());
$entity->setIsActive(true);
$entity->setIsAdmin(true);
$entity->setUserRoles($em->getRepository('UserBundle:Role')->find( $post_send['admin_roles_id'] ));
$entity->setWizardCompleted(true);
$entity->setPath("s");
$em->persist($entity);
$em->flush();
$json = new JsonUtils();
return $json->arrayToJson(array("id"=>$entity->getId()));
}
return $json->arrayToJson( array("sueccess"=>false ) );
}
There's a question here How do I make a ldap search with anonymous binding? related yo my problem, with no answers at all.
Regarding your AD query to check if the user exists (starting at the beginning of your else statement), I would make the logic something like this:
$ldapconn = ldap_connect("10.0.0.230");
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0)
// Use a LDAP service account with only read access...
$searchUser = 'user#myDomain.com';
$searchPass = '12345';
$ldap_success = false;
if (#ldap_bind($ldapconn, $searchUser, $searchPass)) {
$attributes = ['cn'];
$filter = "(&(objectClass=user)(objectCategory=person)(userPrincipalName=".ldap_escape($post_send['username'], null, LDAP_ESCAPE_FILTER)."))";
$baseDn = "DC=myDomain,DC=com";
$results = #ldap_search($ldapconn, $baseDn, $filter, $attributes);
$info = #ldap_get_entries($ldapconn, $results);
$ldap_success = ($info && $info['count'] === 1);
}
In that case $ldap_success would only be true if a user exists in AD with the UPN specified.
However, if you are requiring the user's password and binding to AD, then there is no reason to also verify that the user can be found via a query after binding. In that case simply binding to AD is evidence enough that they exist in AD.
I have a question regarding user membership of groups in Active directory and grabbing such memberships with PHP. My big question/situation is that I have a site I am making and essentially I am trying to assign administrators based off of groups in Active directory and I know how to check member of status on an account but my problem is that there are some groups that aren't displayed there, and one of the groups that is not displayed is the group I need. Is there a way I can check who is a member of that group instead of checking if that user is a member of that group. Alternatively if someone knows why certain groups are not appearing in my search I would prefer to search membership that way because then it would be a simple logic statement to check if the user is in that group, my code is below and it does work but as I said there are certain groups that don't appear and I think I read somewhere about how membership is stored and also if it is a direct membership or if you are a member of a group that is a member of another group. One group that we use as our default group is Domain users but no one has that in there memberOf array even though that group's membership is direct as in the members of that group are all users not other security groups containing the users.
At some point in this program I need to mark certain users as "managers" and the easiest way for me to do so would be to store a flag VIA session variable if they are a member of a certain manager group, as stated above the problem I am running into is users are not appearing in some of their groups so this isn't working, the group that would give access to managers is not appearing in my MemberOf area. During the final stage I will have to go through 5-6 groups and add all the members to the database, it is a similar problem and should have a similar solution so maybe I can kill two birds with 1 stone if I figure that one out too. What I mean by this problem is that I will need to grab a group such as something like 'users HR' and then upload them all to the database by givenname and surname and some default values for other fields but I don't know how to grab users from a group, I know how to grab groups of a user but even that doesn't grab 100% of the groups and if I can reverse that order and act as the group and check my own members that would make things real easy, our current application that we are using to do all this for us is in ASP.net but 10 years old or so and has an administrator account hard coded in to access groups and so on, even doing that I still am not sure how I would get members of a group.
Code:
<?php
$ldap = ldap_connect("192.168.1.**");
$ldap_dn = "DC=************,DC=local";
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
ldap_set_option( $ldap, LDAP_OPT_PROTOCOL_VERSION, 3 );
$access = NULL;
if ($bind = ldap_bind($ldap, "***********\\" . $_POST['username'], $_POST['password'])) {
$filter = "(sAMAccountName=" . $_POST['username'] . ")";
$attr = array("memberof","givenname","sn","mail");
$result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
$entries = ldap_get_entries($ldap, $result);
$givenname = $entries[0]['givenname'][0] . " " . $entries[0]['sn'][0];
ldap_unbind($ldap);
//var_dump($entries[0]["sn"][0]);
//var_dump($givenname);
//var_dump($entries[0]);
// check groups
foreach($entries[0]['memberof'] as $grps) {
// is manager, break loop
//if (strpos($grps, $ldap_manager_group)) { $access = 2; break; }
// is user
//var_dump($grps);
if (strpos($grps, "****** * *** *****")) $access = "****** *";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "***")) $access = "***";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "***")) $access = "***";
}
if ($access != NULL) {
// establish session variables
$_SESSION['user'] = $_POST['username'];
$_SESSION['access'] = $access;
$_SESSION['givenname'] = $givenname;
$_SESSION['email'] = $entries[0]['mail'][0];
return true;
} else {
//echo "No rights?";
// user has no rights
return false;
}
} else {
//header("Location: login.php?Error=Invalid Identity");
echo "Elese Here";
}
?>
Edit:
I have been trying to use this tutorial: samjlevy.com and I understand it for the most part but I am getting a few errors:
Warning: ldap_search(): Search: Operations error in C:\inetpub\wwwroot\InOutBoard\test.php on line 62
Warning: ldap_get_entries() expects parameter 2 to be resource, boolean given in C:\inetpub\wwwroot\InOutBoard\test.php on line 63
Warning: array_shift() expects parameter 1 to be array, null given in C:\inetpub\wwwroot\InOutBoard\test.php on line 66
Warning: Invalid argument supplied for foreach() in C:\inetpub\wwwroot\InOutBoard\test.php on line 72
Array ( )
They all seem to be with the search because it isn't working it's return a NULL set to result which isn't going to allow other parts to run. I am not sure if my $ldap_dn is correct as I am using the same one from the php code above. My layout is as follows (I am new to this I believe this is correct): DC=company,DC=local and so it should be for the group I want: CN=Group Looking For,OU=lowestLevel Ou,OU=Groups,OU=company,DC=Company,DC=local
Would I have to use that as my $ldap_dn?
EDIT 2: (Updated Code)
This code is displaying all the groups that a user is in and works very well, is there a way to write a second page that uses a similar page to take one of those groups and grabs all the members out of it?
<?php
$ldap = ldap_connect("192.168.1.**");
$ldap_dn = "DC=Company,DC=local";
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
ldap_set_option( $ldap, LDAP_OPT_PROTOCOL_VERSION, 3 );
$access = NULL;
if ($bind = ldap_bind($ldap, "**********\\" . $_POST['username'], $_POST['password'])) {
$filter = "(sAMAccountName=" . $_POST['username'] . ")";
$attr = array("memberof","givenname","sn","mail","distinguishedname");
$result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
$entries = ldap_get_entries($ldap, $result);
$givenname = $entries[0]['givenname'][0] . " " . $entries[0]['sn'][0];
//ldap_unbind($ldap);
//var_dump($entries[0]["sn"][0]);
//var_dump($givenname);
//var_dump($entries[0]);
var_dump($entries[0]['distinguishedname'][0]);
$gFilter = "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=".$entries[0]['distinguishedname'][0]."))";
$gAttr = array("cn");
$result1 = ldap_search($ldap, $ldap_dn, $gFilter, $gAttr) or exit("Unable to search LDAP server");
$groups = ldap_get_entries($ldap, $result1);
var_dump($groups);
// check groups
foreach($entries[0]['memberof'] as $grps) {
// is manager, break loop
//if (strpos($grps, $ldap_manager_group)) { $access = 2; break; }
// is user
//var_dump($grps);
if (strpos($grps, "****** * *** *****")) $access = "****** *";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "***")) $access = "***";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "***")) $access = "***";
}
if ($access != NULL) {
// establish session variables
$_SESSION['user'] = $_POST['username'];
$_SESSION['access'] = $access;
$_SESSION['givenname'] = $givenname;
$_SESSION['email'] = $entries[0]['mail'][0];
return true;
} else {
//echo "No rights?";
// user has no rights
return false;
}
} else {
//header("Location: login.php?Error=Invalid Identity");
echo "Elese Here";
}
?>
Second Page: This page is supposed to find members of a group which looks like it may be trying to do so but not picking out members of groups but one of our OU's instead. Look below to code for a layout and what it's grabbing.
<?php
function get_members($group=FALSE,$inclusive=FALSE) {
$ldap_host = "192.168.1.***";
$ldap_dn = "OU=******,OU=*****,OU=**********,DC=Company,DC=local";
$ldap_usr_dom = "#".$ldap_host;
$user = "*******";
$password = "******";
$keep = array(
"samaccountname",
"distinguishedname"
);
$ldap = ldap_connect($ldap_host) or die("Could not connect to LDAP");
ldap_bind($ldap, "REGION5SYSTEMS\\" . $user, $password) or die("Could not bind to LDAP");ry
if($group) $query = "(&"; else $query = "";
$query .= "(&(objectClass=user)(objectCategory=person))";
if(is_array($group)) {
// Looking for a members amongst multiple groups
if($inclusive) {
$query .= "(|";
} else {
$query .= "(&";
}
foreach($group as $g) $query .= "(memberOf=CN=$g,$ldap_dn)";
$query .= ")";
} elseif($group) {
$query .= "(memberOf=CN=$group,$ldap_dn)";
}
if($group) $query .= ")"; else $query .= "";
$results = ldap_search($ldap,$ldap_dn,$query);
$entries = ldap_get_entries($ldap, $results);
array_shift($entries);
$output = array(); // Declare the output array
$i = 0; // Counter
// Build output array
foreach($entries as $u) {
foreach($keep as $x) {
// Check for attribute
if(isset($u[$x][0])) $attrval = $u[$x][0]; else $attrval = NULL;
$output[$i][$x] = $attrval;
}
$i++;
}
return $output;
}
// Example Output
print_r(get_members()); // Gets all users in 'Users'
print_r(get_members("Group I'm search for")); // Gets all members of 'Test Group'
?>
So our DC is DC=CompanyName,DC=Local and we then have folders and OU's and One of the OU's is named 'CompanyName' and nested in it are OU's such as Admins Computers, Contacts, Groups, ect ect... The OU I am looking at is Users and nested within that are different organizations in our building (They use our domian) and one extra OU that is made for this project. Background on the project is a employee inoutBoard and so we have 3 Security groups in that OU, one for other organization's members, one for our organizations members and one for those who are managers from both our Org and their org, basically people who can change status's of others if they forget to do so. What we would ideally want to do is have some sort of sync button which could go check members of those groups and then upload them to the database as well as some default values such as default status of out of office and no description or anything like that. Those groups do not contain people either, they contain other security groups. That's what we want to work, we want to be able to find the members of those groups, the second bit a code I attached will work sometimes, if I set $ldap_dn to "CN=Company,DC=Company,DC=Local" it will print all users in the Users OU and then go into all the OU's there and print the users from those OU's except the OU that we actually need which is that OU that has the groups for the in out board. If I specify that path as the $ldap_dn it just prints array() and nothing else. Any Idea?
The memberOf attribute will only contain direct group memberships, so recursive memberships will not be listed. However, you could specifically query for the recursive group memberships of a user like so (to adapt your code a bit directly after the bind):
$filter = "(sAMAccountName=" . $_POST['username'] . ")";
$attr = array("givenname","sn","mail", "distinguishedname");
$result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
$entries = ldap_get_entries($ldap, $result);
$gFilter = "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=".$entries[0]['distinguishedname'][0]."))";
$gAttr = array("cn");
$result = ldap_search($ldap, $ldap_dn, $gFilter, $gAttr) or exit("Unable to search LDAP server");
$groups = ldap_get_entries($ldap, $result);
Not tested at the moment, but that is the general filter and process for doing it. Get the DN of the user then use the matching rule OID 1.2.840.113556.1.4.1941 to get groups recursively.
The reason you are not getting the "Domain Users" group to show up is because that is a "special" primary group in AD, stored within the primaryGroupId attribute of a user. Additional info on that here:
https://support.microsoft.com/en-us/kb/297951
I am trying to create a login page using PHP.
Goals:
1. The user is able to sign in using the same username/password he uses when logging into Windows
2. The user will be redirected to a page depending on the group he belongs to
So the 1st goal is solved. The problem now is the 2nd goal.
I get an error when I run the script:
Warning: ldap_search(): Search: Bad search filter
Script:
$ldap['user'] = "domain\user123";
$ldap['pass'] = "password123";
$ldap['host'] = 'site.domain.com';
$ldap['port'] = 389;
$ldap['dn'] = "DC=site, DC=domain, DC=com";
$ldap_user_group = "User";
$ldap_manager_group = "Admin";
$ldap['conn'] = ldap_connect( $ldap['host'], $ldap['port'] )
or die("Could not connect to {$ldap['host']}" );
$ldap['bind'] = ldap_bind($ldap['conn'], $ldap['user'], $ldap['pass']);
if( !$ldap['bind'] )
{
echo "Login Failed";
}
else if( $ldap['bind'] )
{
$filter = "(sAMAccountName=" . $ldap['user'] . ")";
$attr = array("memberof");
$result = ldap_search($ldap['conn'],$ldap['dn'], $filter, $attr)
or exit("Unable to search LDAP server");
$entries = ldap_get_entries($ldap['conn'], $result);
ldap_unbind($ldap);
foreach($entries[0]['memberof'] as $grps)
{
if (strpos($grps, $ldap_manager_group))
{
//redirect to Admin page
}
if (strpos($grps, $ldap_user_group))
{
//redirect to User page
}
}
I'm really lost as I have no idea what must be causing this error.
You get a bad search filter as you are passing in a slash into the filter. You are using $ldap['user'] = "domain\user123"; in your filter here $filter = "(sAMAccountName=" . $ldap['user'] . ")";
Depending on your AD setup, you'll probably want to use something like $filter = "(sAMAccountName=user123)";