I searched every days for my problem, I tried many solutions and I didn't find... :(
I want to create an user using ldap_add with PHP. Working fine without enable account and without password. You find the code below.
Can you help me, please?
Config :
PHP 5.6
Windows Server 2012 R2 with AD
I can enable an account when I use $info["useraccountcontrol"]=544; but the account isn't with a password... User must loggon without password and type his new password at the first connection. *
I tried to add a password with $info['userPassword'] and chand useraccountontrol at 512 and I get this error :
ldap_add(): Add: Server is unwilling to perform
Here is my code :
<?php
$name = htmlspecialchars($_POST["name_build"]);
$lastname = htmlspecialchars($_POST["lastname_build"]);
$department = utf8_encode(htmlspecialchars($_POST["department_build"]));
$title = utf8_encode(htmlspecialchars($_POST["title_build"]));
$dn="CN=$name OU=Users, o=Domocom, c=net";
$ds = ldap_connect("192.168.1.1",389);
if ($ds) {
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); // IMPORTANT
ldap_bind($ds, "administrateur#domocom.net", "password");
// Prépareles données
$cn = $info["cn"] = "$lastname $name";
$info["sn"]="$name";
$info["givenname"]="$lastname";
$info["displayname"]="$lastname $name";
$info["name"]="$lastname $name";
$info["userprincipalname"]= "$lastname.$name#domocom.net";
$info["samaccountname"]= "$lastname.$name";
$info["title"]="$title";
$info["department"]="$department";
$info["mail"]="$lastname.$name#domocom.fr";
$info["postalcode"]="69009";
$info["objectClass"][0]="user";
//$info['userPassword'] = "password";
//$info["useraccountcontrol"]=544;
$r = ldap_add($ds,"CN=$cn,OU=Users,OU=Direction,OU=Domocom-SP,DC=domocom,DC=net", $info);
ldap_close($ds);
} else {
echo "unable to connect to ldap server";
}
?>
Thanks a lot.
PS : it's fake society for my school. :p
If it's an AD you might need to use a secure LDAP-Connection.
For that you'll need to call ldap_connect('ldaps://192.168.1.1:<port of the AD>');. Calling ldap_connect with two parameters is deprecated and should be avoided. Use it with an LDAP-URI!
You can also omit the if…else around the ldap_connect as it will return true in almost all cases. And a true return-value does not mean that a connection to the server actually as established. A connection is first established on the first ldap_-command that needs a connection which is typically ldap_bind.
And then you might want to have a look at Change AD password using PHP, Issue updating AD password using PHP and Change AD Password using PHP/COM/ADSI/LDAP
Related
This is my setting:
$base_dn = 'OU=Users,OU=MYCOMPANY_COM,DC=MYCOMPANY,DC=LOCAL';
$ldap_postfix = '#MYCOMPANY.LOCAL';
ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($this->conn, LDAP_OPT_REFERRALS, 0);
$search_filter = '(&(objectCategory=*)(objectClass=*)(SAMAccountName=' . $username . '*))';
Mu ldap is on Microsoft ActiveDirectory.
It works well and I get all parameters of requested username from ldap except info about department.
What am I dooing wrong?
After some investigation I found the problem.
It was due at AD was department empty. After this attribute was filled ldap return it.
Simple and stupid.
Quite new to PHP and LDAP here, looking for some assistance with a personal project (trying to teach myself!).
I would like to password protect certain pages on our website using a simple login box.
My login.php page contains a simple login form with username and password inputs. I have managed to get the login process working using the code below. I am able to use my Active Directory username/pass to login via this form and proceed to the desired page, no issues.
However I'm not sure if I am doing it the 'correct' way.
My code;
ldap.php
session_start();
function authenticate($user, $password) {
if(empty($user) || empty($password)) return false;
$ldaphost = "ad.example.com";
$ldap_dn = "DC=ad,DC=example,DC=com";
$ldap_user_group = "Staff";
$ldap_usr_dom = '#ad.example.com';
$ldap = ldap_connect($ldaphost);
if($bind = ldap_bind($ldap, $user.$ldap_usr_dom, $password) or die ("Error: ".ldap_error($ldap))) {
$filter = "(sAMAccountName=".$user.")";
$attr = array("");
$result = ldap_search($ldap, $ldap_dn, $filter) or exit("Unable to search LDAP server") or die ("Error searching: ".ldap_error($ldap));
$entries = ldap_get_entries($ldap, $result);
ldap_unbind($ldap);
}
foreach($entries[0]['memberof'] as $grps) {
if(empty($grps) || empty($ldap_user_group)) return false;
if(strpos($grps, $ldap_user_group)) {
$access = 1;
} else {
}
}
if($access != 0) {
$_SESSION['user'] = $user;
$_SESSION['access'] = $access;
return true;
} else {
return false;
}
}
I've been told (by someone else) that this particular LDAP authentication process should work in two steps, as follows;
A search is made for the entered user name. I would recommend you use a search user DN and password for this – a user that has search permissions. It binds with these credentials before making the search. If the search succeeds it retrieves the DN of the found user and the search attribute which will later be used to look up the member record.
A second bind is then made with the retrieved user DN and the entered password. If this bind succeeds then the user is authenticated.
My questions are;
Is the above statement correct?
Are two 'binds' necessary?
Can't I just bind the LDAP connection with the credentials the user entered?
Any advice is appreciated, I'm struggling to get my head round the authentication process really :s
Short Answers:
yes
yes
no
Long answer:
Currently you can only bind with the users username and email-address. And that only works with AD as backend. So when you want to do an AD-Authenticator that's OK. But you specificslly asked for an LDAP-Authenticator. And an LDAP bind only works witha DN as the "username". As most of your users will not know that it's easier for them to remember an email-address or a username for a login. So you will need to find the DN to the users login-data. So you will need to do a search in the LDAP and for that you have to bind. So to bind as the user you need to bind... To get around that circular dependency you need to bind first as someone that has read access to the Directory and use that session to find the DN of the user. When found you use that DN and the user-provided password to do a second bind to verify the users credentials.
I did a talk about that just two days ago at zendcon. You can find the slides with some examples at https://heiglandreas.github.io/slidedeck/Directory_Authentication_with_LDAP/20161019%20-%20zendcon/index_online.html
My problem is that when i try to retrieve the value of the attribute 'userPassword' it won't work i'm working under PHP , the problem is that the attribute exist when i open Phpldapadmin i can see it , but when i try to retrieve it using this lines of code it won't work
$sr = ldap_search($ds,"ou=people,dc=powerm,dc=com","uid=".$login);
$data = ldap_get_entries($ds,$sr);
$password = $data[0]["userpassword"][0];
$displayName = $data[0]["displayname"][0];
$num_tel =$data[0]["mobile"][0];
$mail =$data[0]["mail"][0]
the others attributes work fine expect the userpassword
can any one help ?
thanks.
Try specifying the attributes you want returned explicitly.
$dn = 'ou=people,dc=powerm,dc=com';
$filter = 'uid=' . $login;
$attrs = ['displayname', 'userpassword', 'mobile', 'mail'];
$sr = ldap_search($ds, $dn, $filter, $attrs);
The directory may be configured not to return this security-sensitive attribute unless you explicitly ask for it.
It may also be that the attribute requires special privileges to access it - are you using the same credentials to connect to the database in your code as you did in phpLDAPAdmin?
The server may also be configured not to return the password unless it's over an encrypted connection - initiated using an ldaps:// URL passed to ldap_connect(), or using ldap_start_tls().
I'm new(ish) to LDAP, I have managed to list everything fine and I can unlock accounts, however my current task is to do a "name change" for when a user gets married or if we set them up incorrectly etc, what I have so far is failing, please can anyone advise?
thanks
if current $distinguishedname & dn is: CN=Lambo Innit,OU=Services,OU=UserDepartments,OU=North,DC=eng,DC=company,DC=co,DC=uk
and I want to change the distinguishedname and the dn, I'm having problems.$ds is working as I can do other ldap things with this (mod_replace etc)
$newdn = CN=New Name;
$newOU = OU=Services,OU=UserDepartments,OU=North,DC=eng,DC=company,DC=co,DC=uk;
ldap_rename($ds,$distinguishedName,$newdn,$newOU,true);
EDITED to make it easier to read
Thanks for your post, you helped me figure out how to move a user from the OU=Contractors group to the OU=Employees Group
//variables
$ds1 = ldap_connect( <<your ldap connection>> );
$cn = 'firstname lastname';
$dn = 'CN='.$cn.',OU=Contractors,DC=AD,DC=MYCOMPANYNAME,DC=COM';
$newcn = 'CN='.$cn; //I use same value, since I don't want to change it
$newOU = 'OU=employees,DC=AD,DC=MYCOMPANYNAME,DC=COM';
//update Active Directory
ldap_rename($ds1, $dn, $newcn, $newOU, true);
I have this script through which I can change my LDAP password but I also want to change my username or full name or email or phone number. How can I do that? When I echo out the records I only get info like my name and email but what do I need to do to make ldap_modify change my full name or phone number or email or userid?
<?php
$server = "ldap://ldap";
$dn = "ou=People,DC=ssdfg,DC=sadad,DC=com";
$message = array();
function changePassword($server,$dn,$user,$oldPassword,$newPassword,$newPasswordCnf){
global $message;
error_reporting(0);
$con=ldap_connect($server);
ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
$findWhat = array ("cn","mail");
$findWhere = $dn;
$findFilter = "(uid=$user)";
#bind anon and find user by uid
$sr = ldap_search($con,$dn,$findFilter,$findWhat);
$records = ldap_get_entries($con, $sr);
echo "<pre>";print_r($records);
/* error if found more than one user */
if ($records["count"] != "1") {
$message[] = "Error E100 - Wrong user.";
return false;
}else {
$message[] = "Found user <b>".$records[0]["cn"][0]."</b>";
}
/* try to bind as that user */
if (ldap_bind($con, $records[0]["dn"], $oldPassword) === false) {
$message[] = "Error E104 - Current password is wrong.";
return false;
}
else { }
if ($newPassword != $newPasswordCnf ) {
$message[] = "Error E101 - New passwords do not match! ";
return false;
}
if (strlen($newPassword) < 8 ) {
$message[] = "Error E102 - Your new password is too short! ";
return false;
}
if (!preg_match("/[0-9]/",$newPassword)) {
$message[] = "Error E103 - Your password must contain at least one digit. ";
return false;
}
if (!preg_match("/[a-zA-Z]/",$newPassword)) {
$message[] = "Error E103 - Your password must contain at least one letter. ";
return false;
}
/* change the password finally */
$entry = array();
$entry["userPassword"] = "{SHA}" . base64_encode( pack( "H*", sha1( $newPassword ) ) );
if (ldap_modify($con,$records[0]["dn"],$entry) === false){
$message[] = "E200 - Your password cannot be change, please contact the administrator.";
}
else {
$message[] = " Your password has been changed. ";
//mail($records[0]["mail"][0],"Password change notice : ".$user,"Your password has just been changed.");
}
}
?>
Change your $findwhat variable to have a * in it and you will get all of the user attributes that your account you are executing the search with can see. Note that anonymous might not be able to see much and it certainly won't be able to update much. My advice is to create an account in your directory that has all the privileges you will need and do all of your operations under that (except for authentication of course).
Modifying the other attributes should just be a matter of including them in your $entry array. You need to use the proper attribute names but you'll see them when you print them out after changing $findwhat to a *.
Also Apache Directory Studio is a nice free tool for working with directories. One thing cool about it is that you can view the search and modification logs and see the ldif operations it is sending to the directory. Then you can replicate that in your code.
Attributes must be requested unless the ALL_ATTRIBUTES value is used, often this is an asterisk, but not always. The directory server must allow clients to retrieve values, and userPassword is often restricted to users with more privileges.
To modify attribute values, construct a modify request with the distinguished name, attribute, and the new values.
There are couple things of note:
The LDAP client should check for response controls when the server transmits a response to a request. Failure to check for response controls will result in the LDAP client possibly missing important information from the server
Why does this client base 64 encode the password? Directory server should never accept pre-encoded passwords (servers should be configured to reject pre-encoded passwords) because the server cannot execute password quality and history checks on pre-encoded passwords. For these and other reasons, transmitting pre-encoded passwords are a terrible idea, and all clients should reject this practice. LDAP clients must use a secure connection (SSL, TLS, or ipsec) and transmit passwords in the clear or use an external SASL bind request. For even better security use the password modify extended request which requires the existing password, and can generate a password for the user.
This client does not appear to be able to respond to an unsolicited notification from the server. Directory Servers may transmit an extended result that is unsolicited, that is, not in response to a client request. Clients must be able to handle these notifications which are often notifications that the server disconnected the client for whatever reason.
For more information, please see "LDAP: Programming Practices".