ldapsearch on dn working, but not with php - php

I'm working with a service provider, who handles the hosting of the virtual server and the configuration of the LDAP server.
My job is to create a PHP application that use the LDAP to create a user at login (to keep things simple).
After many shares with the service provider, I finally achieve to contact the LDAP server with the following:
ldapsearch -x -LLL -h vmdc2.local -D email#local -w myPassword -b"CN=xxx,OU=APPLICATIF,OU=GROUPES,OU=UTILISATEUR,DC=enterprise,DC=local"
It comes from the ldap-utils Linux packet. This query returns good results.
So I created a simple script, trying to use the previous DN to list the users in CLI, for proof of work in PHP.
<?php
// create connection to LDAP server
$ldapconn = ldap_connect("ldap://vmdc2.local")
or die("Impossible to connect to the LDAP server.");
$ldapbind = ldap_bind($ldapconn, 'email#local', 'myPassword');
// check binding
if ($ldapbind) {
echo "Successfully connected to LDAP !" . PHP_EOL;
$dn = 'CN=xxx,OU=APPLICATIF,OU=GROUPES,OU=UTILISATEUR,DC=enterprise,DC=local';
$sr = ldap_list($ldapconn, $dn, 'cn=*');
if (false === $sr) {
die('Impossible to use the dn: ' . $dn . PHP_EOL);
}
$info = ldap_get_entries($ldapconn, $sr);
if ($info['count'] === 0) die('No entries :(');
for ($i=0; $i < $info["count"]; $i++) {
echo $info[$i]["cn"][0] . PHP_EOL;
}
} else {
$var = '';
ldap_get_option($ldapconn, LDAP_OPT_ERROR_STRING, $var);
echo "Connection to LDAP failed..." . PHP_EOL . $var . PHP_EOL;
}
The script output No entries :(
My questions
How can I get a different result from PHP on the same DN?
It is possible to configure how the LDAP server can answer, in the function of who is calling him?
It's my first time against LDAP, so I'm lost :/ Your help is really welcome!

Related

Ubuntu server able to connect via LDAP but not LDAPS though LDP shows SSL is enabled

I've installed Ubuntu Desktop 18.04 and LAMP, enabled LDAP, etc. I am able to connect via LDAP and port 389. When I attempt to connect with LDAPS on 636, I get blocked out. I've used LDP in Windows to connect to the server to verify SSL is enabled and I can connect to the server using SSL within the LDP program.
This is a fresh virtual machine with a bridged network connection running Ubuntu 18.04 desktop. I've tried multiple sets of code and different AD user accounts from basic user accounts to domain admin accounts.
<?php
$ldaphost = "ldaps://my.domain.controller"; //edited for security purposes
$ldapport = 636;
$lconn = ldap_connect($ldaphost) // also tried $lconn = ldap_connect($ldaphost,$ldapport); to no avail
or die("Could not connect to host!");
As mentioned, it works if I change it to standard LDAP so I know that's enabled correctly. I've been searching online for hours and nothing else has helped.
The LDP program provides the following information:
0x0 = ldap_unbind(ld);
ld = ldap_sslinit("my.domain.controller", 636, 1);
Error 0 = ldap_set_option(hLdap, LDAP_OPT_PROTOCOL_VERSION, 3);
Error 0 = ldap_connect(hLdap, NULL);
Error 0 = ldap_get_option(hLdap,LDAP_OPT_SSL,(void*)&lv);
Host supports SSL, SSL cipher strength = 256 bits
Established connection to my.domain.controller.
Retrieving base DSA information...
Getting 1 entries:
EDIT: Ended up being a cert error. They weren't set up properly by the previous administration. Working on fixing them now.
You are going to need to verify a few things:
CA cert from the DC is installed on the Ubuntu Server.
SSL cert signed from the CA with the FQDN (or IP- depending on how your LDAPS uri is written) in the CN of the cert is installed on the Ubuntu Server.
If using openldap for any part of connecting, modify your ldap.conf like so:
BASE dc=domain,dc=com
URI ldaps://dc.domain.com:636
TLS_CACERT /path/to/ca-cert.cer
TLS_REQCERT DEMAND
and then ldap search should return results with a query similar to:
ldapsearch -x -H ldaps://dc.domain.com -D 'CN=LDAP-bind,OU=Service Accounts,OU=Accounts,DC=domain,DC=com' -W -b 'OU=Accounts,DC=domain,DC=com'
These are the instructions I followed when I setup my web apps to authenticate over LDAPS → Enable LDAP over SSL for Microsoft Active Directory servers
This is the code I use to test my LDAPS connection from different client servers.
class LDAP {
public function connect($host, $user, $pass){
$ds = ldap_connect($host);
if(!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)){
print "Could not set LDAPv3";
} else {
$ldap = ldap_bind($ds, $user, $pass);
}
if(strpos($host, 'ldaps://') !== false){
$ssl = ' over SSL';
$host = str_replace('ldaps://', '', $host);
} else {
$ssl = null;
$host = str_replace('ldap://', '', $host);
}
if($ldap) {
//$host = str_replace('ldap://', replace, subject)
echo '<b>LDAP</b> : <u>Microsoft AD</u> <br /><br />
Connection to <u>' . $host . '</u>' . $ssl . ' was successful! <br /><br />
[WebServer] ←→ [LDAP Server] <br /><br />
<b>Status:</b> <u>Up</u> ✔ <br />';
} else {
echo 'Connection to <u>' . $host . '</u>' . $ssl . ' was NOT successful. Please try again. <br /><br />
[WebServer] ←x→ [LDAP Server] <br /><br />
<b>Status:</b> <u>Down</u> ✖ <br />';
}
}
public function disconnect(){
$ldap = null;
}
} # class ldap
$LDAP = new LDAP();
$host = "ldaps://dc.domain.com";
$user = "svc.ldap#domain.com";
$pass = "password1";
$LDAP->connect($host, $user, $pass);
$LDAP->disconnect();
// echo 'HOST['.$host.'] USER['.$user.']'; // toggle to troubleshoot db connection

not able to bind using ldap_bind through PHP

I am able to connect to LDAP through unix but when I try to do the same through PHP am not able to. Below is the code,
$server ='server';
$port = 3060;
$ldapconn = ldap_connect($server, $port) or die("Could not connect " .
$server . ":" . $port . ".");
$user = "cn=orcladmin";
$password ='password';
$ldapbind = ldap_bind($ldapconn,$user,$password) ;
if(!$ldapbind)
{
echo ldap_error($ldapconn); #I get error invalid credentials
}
I am able to connect and also bind anonymously but in that case ldap_search does not work which is my final requirement. using the same credentials i.e cn=orcladmin and 'password' I am able to connect to ODSM.
Also Ihave tested the connection using below on unix,
ldapbind -h 'server' -p 3060 -D "cn=orcladmin" -w 'password'
it gives below message:
bind successful
Is user specified differently while connecting through PHP?
Could someone please help?
the issue was with ORACLE_HOME, not sure how to set it in PHP but I wrote a shell script where ORACLE_HOME was set and able to successfully run ldapbind and ldapsearch.

PHP LDAP search issue

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!

Do I need ldap.conf when I connect to Active Directory using PHP?

I'm trying to authenticate to Active Directory using PHP (5.3.2)/Apache (2.0.59)/Windows (2003).
However, I'm getting the following error:
ldap_start_tls() [function.ldap-start-tls]: Unable to start TLS: Connect error in E:\my_page.php on line 15
Here is my current script:
putenv('LDAPTLS_REQCERT=never');
$resource = ldap_connect("xxx")
or die("Failed to connect to LDAP server.");
echo "Connected to LDAP server.<br />";
//these options may not be necessary in all environments
ldap_set_option($resource, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($resource, LDAP_OPT_REFERRALS, 0);
$result = ldap_start_tls($resource) or die("Failed to start TLS.<br />");
echo "Started TLS.<br />";
$result = ldap_sasl_bind($resource, NULL, '', 'GSSAPI', 'xxx', '', '')
or die("Failed to GSSAPI bind.<br />");
echo "GSSAPI bound.";
I've looked at this question for help, however, I keep seeing references to ldap.conf.
Is this for OpenLDAP as in, the LDAP server your connecting to? If it is, I could ignore it due to using an existing enteprise Active Directory ?
Or is this for the PHP libraries connecting to an LDAP server (ie. ldap_connect())?
Edit #1
Screenshot of Wireshark...
I see in there, unknown CA... how would I go solving this (looking online ATM).
Edit #2
Update, I'm now getting a different error. I created ldap.conf on c:\ and c:\openldap\sysconf
Content of ldap.conf:
#
# LDAP Defaults
#
TLS_REQCERT never
Now, it's stuck at the ldap_sasl_bind method which is normal - it's not installed.
Edit #3
Final product:
function isAuthenticated($user, $pass){
//init
$ldap_server = "";
$ldap_user = "";
$ldap_pass = "";
$ldap_dn = "";
$ldap_filter_fields = array("dn","cn","samaccountname");
//establish connection
$ldap_conn = ldap_connect($ldap_server)
or die("Failed to connect to LDAP server.");
//these options may not be necessary in all environments
ldap_set_option($resource, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($resource, LDAP_OPT_REFERRALS, 0);
//Magic happens here, encrypted tunnel starts!
$result = ldap_start_tls($ldap_conn) or die("Failed to start TLS.<br />");
$out = 0;
//connect using our known user
if($bind = ldap_bind($ldap_conn, $ldap_user, $ldap_pass)){
//search for the user
$ldap_search_results = ldap_search($ldap_conn, $ldap_dn, "samaccountname=".$user, $ldap_filter_fields) or die ("Failed to search LDAP");
//get entry
$ldap_record = ldap_get_entries($ldap_conn, $ldap_search_results);
debug($ldap_record);
if($ldap_record["count"] > 0){
//try to authenticate user here
if($bind2 = #ldap_bind($ldap_conn, $ldap_record[0]["dn"], $pass))
$out = 1;
else
//wrong password
$out = 0;
}
else
//user wasn't found
$out = 3;
}
else
//something happened when connecting with our ldap_user
$out = 2;
return $out;
}
You're on the right track with your unknown CA. I have had a similar issue with PHP on CentOS connecting to AD. I had to export the CA certificate from the AD server and configure it to be trusted on the CentOS system, which involved copying the certificate to /etc/openldap/cacerts and running OpenSSL's c_rehash. Unfortunately, I'm not sure how to tell you to get that same setup working under Windows.
Yes you are required to change the ldap.conf file and change the value of TLS_REQCERT to demand if you are trying to connect with the AD for which the trust has not been established on your host machine running Apache. If you have certificate from a trusted CA i.e. already installed on the machine OS keystore then it may run with the TLS_REQCERT set to never otherwise you will have to explicitly give the certificates and change the variable TLS_REQCERT.

LDAP and PHP connection failure

I am trying to connect to a secure LDAP server (using LDAPs) via PHP, but I am having problems with it. I get the following error
Warning: ldap_bind() [function.ldap-bind]: Unable to bind to server: Can't contact LDAP server in /var/www/test.php on line 16
I works when I try to connect without LDAPs, but it is required that I use LDAPs because I am going to be dealing with sensitive information.
I am using the following code
<?php
// basic sequence with LDAP is connect, bind, search, interpret search
// result, close connection
echo "<h3>LDAP query test</h3>";
echo "Connecting ...";
$ds=ldap_connect("ldaps://server"); // must be a valid LDAP server!
print $ds;
if ($ds) {
echo "<br><br>Binding ...";
$r=ldap_bind($ds); // this is an "anonymous" bind, typically
// read-only access
echo "Bind result is " . $r . "<br />";
echo "Searching for (sn=S*) ...";
// Search surname entry
$sr=ldap_search($ds, "ou=people,o=server.ca,o=server", "uid=username*");
echo "Search result is " . $sr . "<br />";
echo "Number of entires returned is " . ldap_count_entries($ds, $sr) . "<br />";
echo "Getting entries ...<p>";
$info = ldap_get_entries($ds, $sr);
echo "Data for " . $info["count"] . " items returned:<p>";
print_r($info);
// for ($i=0; $i<$info["count"]; $i++) {
// echo "dn is: " . $info[$i]["dn"] . "<br />";
// echo "first cn entry is: " . $info[$i]["cn"][0] . "<br />";
// echo "first email entry is: " . $info[$i]["mail"][0] . "<br /><hr />";
// }
echo "Closing connection";
ldap_close($ds);
} else {
echo "<h4>Unable to connect to LDAP server</h4>";
}
?>
The problem is not related to the actual binding process (invalid credentials) as the warning would be a different one if the LDAP server could not authenticate your credentials. But as Paul Dixon noted the use of ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3) should be required - even though I don't think that this is the cause of your problems.
Which LDAP server type are you connecting to? OpenLDAP, Active Directory or something else?
What's the operating system of the computer running your PHP program?
Are you using a self-signed SSL certificate on the LDAP server and is the certificate authority for the given certificate trusted by the machine running your PHP program?
Which port does the LDAP server run on? 636 would be the "official" port for LDAPS. Perhaps you can add the port explicitly to the server address: ldaps://<<server>>:636.
ext/ldap has some issues with SSL/TLS secured connections. You can try to add
TLS_REQCERT never
to the ldap.conf (/etc/ldap.conf or /etc/ldap/ldap.conf on *nix-based systems) or for Windows machines create a ldap.conf with the above content in C:\OpenLDAP\sysconf\ldap.conf (the path must be an exact match as it's hard-coded into the extension).
It appears to be a problem using SSL/TLS on some servers with recent PHP versions. Not sure why. You can refer to my post at: Problems with secure bind to Active Directory using PHP
One of the more likely causes, is the cause from Stefan. To make sure that this is really the case, you can use:
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
before your ldap_connect. This will print a more sane error message to log (typically ssl cert not valid, ref. Stefan Gehrig)
Although old, I have encountered the same issue and wanted to provide some insight for future readers.
Part of the problem was out-of-date OpenSSL libraries, 0.9.6 vs 1.0.0 (which worked).
After updating OpenSSL on the server, it was noted that PHP lost support for OpenSSL.
You can check support for modules with the following from the command line:
php -m
Or
echo phpinfo(INFO_MODULES);
From the browser.
Also, there have been a lot of issues with SSL Support for LDAP when using the OCI8/Oracle LDAP libs in my professional experience. On Debian platforms, Libldap-2.4.2-dev packages work best.
Additionally, you should look at the connection logs on the LDAP server. I can almost guarantee that you will see an error referring to SSLv3 and missing a CA for the certificate.
By default, PHP looks for the CA file on UNIX systems in, make sure it is readable by the PHP invoker (user via cli, Apache user, etc..):
/etc/pki/CA
This is not necessarily a PHP issue, but a configuration issue with Secure LDAP. Please see this PHP bug report and this OpenLDAP thread.
The OpenLDAP thread above has a snippet of a working OpenLDAP config for reference.
Some other things to check is your services definitions in /etc/services. Make sure you have the following:
ldaps 636/tcp # LDAP over SSL
ldaps 636/udp
I think you just need to set the ldap protocol version to be 3
echo "<h3>LDAP query test</h3>";
echo "Connecting ...";
$ldap_server = 'ldaps://server';
$ldap_port = '636';
$ds = ldap_connect($ldap_server, $ldap_port);
if ($ds)
{
//add this
if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3))
{
fatal_error("Failed to set LDAP Protocol version to 3, TLS not supported.");
}
echo "<br><br>Binding ...";
$r=ldap_bind($ds); // this is an "anonymous" bind, typically
// read-only access
echo "Bind result is " . $r . "<br />";
echo "Searching for (sn=S*) ...";
// Search surname entry
$sr=ldap_search($ds, "ou=people,o=server.ca,o=server", "uid=username*");
echo "Search result is " . $sr . "<br />";
echo "Number of entires returned is " . ldap_count_entries($ds, $sr) . "<br />";
echo "Getting entries ...<p>";
$info = ldap_get_entries($ds, $sr);
echo "Data for " . $info["count"] . " items returned:<p>";
print_r($info);
// for ($i=0; $i<$info["count"]; $i++) {
// echo "dn is: " . $info[$i]["dn"] . "<br />";
// echo "first cn entry is: " . $info[$i]["cn"][0] . "<br />";
// echo "first email entry is: " . $info[$i]["mail"][0] . "<br /><hr />";
// }
echo "Closing connection";
ldap_close($ds);
}
else
{
echo "<h4>Unable to connect to LDAP server</h4>";
}
On UNIX "man ldap.conf" = ... SYNOPSIS /usr/local/etc/openldap/ldap.conf ...
Write TLS_REQCERT never in /usr/local/etc/openldap/ldap.conf
and set ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)
This work in my project on Nginx+PHP-fpm:
nginx/1.6.0
php55-5.5.15
php55-ldap-5.5.15
openldap-client-2.4.39_1
What saved my day after reading and trying out solutions from allover the web and SO, was to use a ldaps uri without the port specified in it.
So instead of this: ldaps://example.com:636 I had to use this: ldaps://example.com and it now works like a charm.
I was setting this up on Ubuntu 16.04 with PHP7.3 runing through Nginx and php-fpm.
A full code example:
try{
$ldapUri = "ldaps://example.com";
$ldapUsername = 'username';
$ldapPassword = 'password';
$ldapConn = ldap_connect($ldapUri);
if($ldapConn){
ldap_set_option($ldapConn,LDAP_OPT_NETWORK_TIMEOUT,10);
if(!ldap_set_option($ldapConn,LDAP_OPT_PROTOCOL_VERSION,3)){
print 'Failed to set ldap protocol to version 3<br>';
}
ldap_set_option($ldapConn, LDAP_OPT_REFERRALS,0);
$ldapBind = ldap_bind($ldapConn, $ldapUsername, $ldapPass);
if ($ldapBind) {
echo "LDAP bind successful...";
//DO LDAP search and stuff
ldap_unbind($ldapConn);
} else {
echo "LDAP bind failed...";
}
}
}catch(Exception $e){
print($e->getMessage();
}
Try to enable "anonymous binds" on your LDAP-Server or use a correct bind (username / password).
like cn=ldapauthuser,ou=accounts,dc=example,dc=com

Categories