How can i manage an ldap_search() Operations error? - php

I'm trying to use an LDAP query to get my AD groups of one of my divisions, I've written this for the moment:
<?php
session_start();
//::::::::DEBUG::::::::\\
//echo $_SESSION['login_session'];
//echo "<br>";
//echo $_SESSION['password_session'];
//echo "<br>";
//echo $_SESSION['AD_session'];
//$_SESSION['AD_session']=ldap_conect(XXX.XXX.XXX,389) but i apparently cannot conserve this function in a $_SESSION var...
//echo "<br>";
//echo $_SESSION['DN_SESSION'];
//"OU=XXX,DC=XXX,DC=XXX"
//echo "<br>";
//::::::::DEBUG::::::::\\
//----------------------------------------------------------------------------------------------------
//::::::::SECURITY FUNCTION::::::::\\
if (NULL!==($_SESSION['login_session']&&$_SESSION['password_session'])){
//::::::::SECURITY FUNCTION::::::::\\
//----------------------------------------------------------------------------------------------------
//::::::::VARIABLES::::::::\\
$filter = "(CN=*)";
$attr = array("OU","CN","DC");
//::::::::VARIABLES::::::::\\
//----------------------------------------------------------------------------------------------------
//::::::::LDAP's setting::::::::\\
ldap_set_option(ldap_connect("XXX.XXX.XXX",389), LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option(ldap_connect("XXX.XXX.XXX",389), LDAP_OPT_REFERRALS, 0);
//::::::::LDAP's setting::::::::\\
//----------------------------------------------------------------------------------------------------
//::::::::LDAP BIND::::::::\\
ldap_bind(ldap_connect("XXX.XXX.XXX",389),"CN=".$_SESSION['login_session'].",OU=XXX,OU=XXX,DC=XXX,DC=XXX", $_SESSION['password_session']);
//::::::::LDAP BIND::::::::\\
//----------------------------------------------------------------------------------------------------
//::::::::REQUESTS VARIABLES::::::::\\
$result = ldap_search(ldap_connect("XXX.XXX.XXX",389),$_SESSION['DN_SESSION'], $filter, $attr);
$rescount = ldap_count_entries(ldap_connect("XXX.XXX.XXX",389),$result);
$data = ldap_get_entries(ldap_connect("XXX.XXX.XXX",389),$result);
//::::::::REQUESTS VARIABLES::::::::\\
//----------------------------------------------------------------------------------------------------
//::::::::RESULTS DISPLAY::::::::\\
echo '<pre>';
foreach($data as $row) {
print_r($row);
}
//::::::::RESULTS DISPLAY::::::::\\
//----------------------------------------------------------------------------------------------------
?>
The binding function is working well and I'm using a valid user to query my AD groups. But I get an "ldap_search(): Search: Operations error" message on my ldap_search query. I've searched for a moment on different forums and I saw some solutions: setting the protocol and referral of the AD, which I've done in my LDAP's setting part, I also saw that some people get this error because they were using DN instead of DC in the distinguished name that they wanted to reach but it is not my case...
Is someone have an idea of what's the problem in my code ? Thanks a lot.

Operations Error means there is an error in the sequencing of operations.
LDAP is a connected protocol, which means that you first connect to it, and then you issue multiple operations on that connection, the first one being a Bind to authenticate the user.
In your code, you are creating a new connection for each operation with ldap_connect("XXX.XXX.XXX",389). Do this once, pass the connection to all other calls as a variable, and things should work.

Related

PHP SQL query doesnt return a result

I have a button in a webapp that allows users to request a specially formatted number. When a user click this button 2 scripts run. The first that is fully functional, looks at a number table finds the largest number and increments it by 1. (This is not the Primary Key) the second script which is partially working gets the current date and runs a SQL query to get which period that date falls in. (Periods in this case not always equaling a full month) I know this script is at least partially working because I can access the $datetoday variable called in that script file. However it is not returning the requested data from the periods table. Anyone that could help me identify what I am doing wrong?
<?php
include 'dbh.inc.php';
$datetoday = date("Ymd");
$sql = "SELECT p_num FROM periods where '$datetoday' BETWEEN p_start AND p_end";
$stmt = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../quote.php?quotes=failed_to_write");
exit();
} else {
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$result = mysqli_stmt_get_result($stmt);
$row = mysqli_fetch_assoc($result);
$pnum = $row;
mysqli_stmt_close($stmt);
}
If it helps any one I published my code to https://github.com/cwilson-vts/Quote-Appliction
So first off, I do not use msqli and never learned it. However, I believe I get the gist of what you want to do. I use PDO because I FEEL that it is easier to use, easier to read and it's also what I learned starting off. It's kinda like Apple vs. Samsung... no one product is exactly wrong or right. And each have their advantages and disadvantages. What I'm about to provide you will be in PDO form so I hope that you will be able to use this. And if you can't then no worries.
I want to first address one major thing that I saw and that is you interlacing variables directly into a mysql statement. This is not considered standard practice and is not safe due to sql injections. For reference, I would like you to read these sites:
http://php.net/manual/en/security.database.sql-injection.php
http://php.net/manual/en/pdo.prepared-statements.php
Next, I'm noticing you're using datetime as a variable name. I advise against this as this is reserved in most programming languages and can be tricky. So instead, I am going to change it something that won't be sensitive to it such as $now = "hello world data";
Also I'm not seeing where you would print the result? Or did you just not include that?
Another thing to consider: is your datetime variable the same format as what you are storing in your db? Because if not, you will return 0 results every time. Also make sure it is the right time zone too. Because that will really screw with you. And I will show you that in the code below too.
So now on to the actual code! I will be providing you with everything from the db connection code to the sql execution.
DB CONNECTION FILE:
<?php
$host = '127.0.0.1';
$user = 'root';
$pw = '';
$db = 'test'; // your db name here (replace 'test' with whatever your db name is)
try {
// this is the variable will call on later in the main file
$conn = new PDO("mysql:host=$host;dbname=$db;", $user, $pw);
} catch (PDOException $e) {
// kills the page and returns mysql error
die("Connection failed: " . $e->getMessage());
}
?>
The data file:
<?php
// calls on the db connection file
require 'dbconfig.php';
// set default date (can be whatever you need compared to your web server's timezone). For this example we will assume the web server is operating on EST.
date_default_timezone('US/Eastern');
$now = date("Ymd");
// check that the $now var is set
if(isset($now)) {
$query = $conn->prepare("SELECT p_num FROM periods WHERE p_start BETWEEN p_start AND :now AND p_end BETWEEN p_end AND :now");
$query->bindValue(':now', $now);
if($query->execute()) {
$data = $query->fetchAll(PDO::FETCH_ASSOC);
print_r($data); // checking that data is successfully being retrieved (only a troubleshooting method...you would remove this once you confirm it works)
} else {
// redirect as needed and print a user message
die("Something went wrong!");
}
$query->closeCursor();
}
?>
Another thing I want to mention is that make sure you follow due process with troubleshooting. If it's not working and I'm not getting any errors, I usually start at the querying level first. I check to make sure my query is executing properly. To do that, I go into my db and execute it manually. If that's working, then I want to check that I am actually receiving a value to the variable I'm declaring. As you can see, I check to make sure the $now variable is set. If it's not, that block of code won't even run. PHP can be rather tricky and finicky about this so make sure you check that. If you aren't sure what the variable is being set too, echo or print it with simply doing echo $now
If you have further questions please let me know. I hope this helps you!
I think I know what I was doing wrong, somebody with more PHP smarts than me will have to say for sure. In my above code I was using mysqli_stmt_store_result I believe that was clearing my variable before I intended. I changed that and reworked my query to be more simple.
<?php
include 'dbh.inc.php';
$datetoday = date("Ymd");
$sql = "SELECT p_num FROM periods WHERE p_start <= $datetoday order by p_num desc limit 1";
$stmt = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../quote.php?quotes=failed_to_write");
exit();
} else {
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while( $row = mysqli_fetch_assoc($result)) {
$pnum = $row['p_num'];
echo $pnum;
}
mysqli_stmt_close($stmt);
}
Thanks to #rhuntington and #nick for trying to help. Sorry I am such an idiot.

PHP login script using bind_result in subsequent query mysqli

I'm trying to build a relatively simple PHP login script to connect to MySQL database running on my home server. I know the connection works as I've gotten some data returned as I would expect. However, I am having trouble getting the full script to work.
Essentially, I'm taking in a username/password from the user, and I first do a lookup to get the user_id from the users table. I then want to use that user_id value to do a comparison from user_pswd table (i'm storing usernames and passwords in separate database tables). At one point, I was able to echo the correct user_id based on the username input. But I haven't been able to get all the issues worked out, as I'm pretty new to PHP and don't really know where to see errors since I load this onto my server from a remote desktop. Can anyone offer some advice/corrections to my code?
The end result is I want to send the user to another page, but the echo "test" is just to see if I can get this much working. Thanks so much for the help!
<?php
ob_start();
$con = new mysqli("localhost","username","password","database");
// check connection
if (mysqli_connect_errno()) {
trigger_error('Database connection failed: ' . $con->connect_error, E_USER_ERROR);
}
$users_name = $_POST['user'];
$users_pass = $_POST['pass'];
$user_esc = $con->real_escape_string($users_name);
$pass_esc = $con->real_escape_string($users_pass);
$query1 = "SELECT user_id FROM users WHERE username = ?;";
if ($result1 = $con->prepare($query1)) {
$result1->bind_param("s",$user_esc);
$result1->execute();
$result1->bind_result($userid);
$result1->fetch();
$query2 = "SELECT user_pswd_id FROM user_pswd WHERE active = 1 AND user_id = ? AND user_pswd = ?;";
if ($result2 = $con->prepare($query2)) {
$result2->bind_param("is",$userid,$pass_esc);
$result2->execute();
$result2->bind_result($userpswd);
$result2->fetch();
echo "test", $userpswd;
$result2->free_result();
$result2->close();
} else {
echo "failed password";
}
$result1->free_result();
$result1->close();
}
$con->close();
ob_end_clean();
?>

Failure of PHP AD LDAP script ONLY when passed variables

Sample AD LDAP Live Lookup PHP from Helpspot
Okay so I am using the above sample php LDAP script to lookup user info in our ticketing system. I am running into some issues however (these are probably due to my very rudimentary understanding of PHP). I know the script is sort of working because if I hit the URL for the script in my browser it will spit back a list of all users in the domain until it hit the return limit and just stops. I am sure I could get it to spit back more, but that is not really the issue right now. Because I am getting data from my domain I am assuming that my creds and binds are good in the script. We use the credentials, server, etc on all our MFP's for their global address list without issue so I am positive I am good there. The problem arises when you pass anything to it to do a lookup. I receive an error that states:
ldap search failed: Operations error
When I tweak the script to give me a little more info it points me back to this line:
$search = ldap_search($ad, $dn, $filter, $attrs)
or die ("ldap search failed: ".ldap_error($ad));
Which I had suspected given the error I was getting is present in this line. So I am assuming one of those defined variables is the culprit causing me problems. This is where i start to get lost. I am not understanding why asking it to narrow the results returned would break this? Any suggestions? Or is there anything more I need to share?
Thank you #heiglandreas that post helped me immensely. Using the script being run in that section I was able to grab some pieces that allowed my script to function properly. I am not sure exactly why my environment didn't care for my first script, I suspect the change in location in the script of certain steps and the changed formatting of the bind helped. My script now looks like:
<?php
header('Content-type: text/xml');
$hostname="ldap://SERVER IP ADDRESS";
$ds=ldap_connect($hostname, 389);
$user = "domain\username";
$pswd = "PASSWORD";
ldap_set_option ($ds, LDAP_OPT_REFERRALS, 0) or die('Unable to set LDAP opt referrals');
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3) or die('Unable to set LDAP protocol version');
if ($ds)
{
$dn = "DC=DOMAIN,DC=local";
if (!($ldapc=ldap_bind($ds, $user, $pswd))) {
echo "<p>Error:" . ldap_error($ds) . "</p>";
echo "<p>Error number:" . ldap_errno($ds) . "</p>";
echo "<p>Error:" . ldap_err2str(ldap_errno($ds)) . "</p>";
die;
}
$attributes = array('employeeID','givenname','sn','mail','telephoneNumber');
if(!empty($_GET['customer_id'])){ //If an ID is passed in use that to make a direct lookup
$filter = 'employeeID='.$_GET['customer_id'].'*';
}elseif(!empty($_GET['email'])){ //If no ID then try email
$filter = 'mail='.$_GET['email'].'*';
}elseif(!empty($_GET['last_name'])){ //If no ID or email then search on last name
$filter = 'sn='.$_GET['last_name'].'*';
}elseif(!empty($_GET['first_name'])){ //Try first name if no ID,email,last name
$filter = 'givenname='.$_GET['first_name'].'*';
}else{
$filter = 'sn='.'*'; //Return everyone
}
$search = ldap_search($ds, $dn, $filter, $attributes)
or die ("ldap search failed: ".ldap_error($ds));
$entries = ldap_get_entries($ds, $search);
echo '<?xml version="1.0" encoding="utf-8"?>';
}
?>
<livelookup version="1.0" columns="first_name,last_name, email">
<?php for ($i=0; $i < $entries["count"]; $i++) : ?>
<customer>
<customer_id><?php if(isset($entries[$i]['employeeID'][0])){ echo htmlspecialchars($entries[$i]['employeeID'][0]); } ?></customer_id>
<first_name><?php if(isset($entries[$i]['givenname'][0])){ echo htmlspecialchars($entries[$i]['givenname'][0]); } ?></first_name>
<last_name><?php if(isset($entries[$i]['sn'][0])){ echo htmlspecialchars($entries[$i]['sn'][0]); } ?></last_name>
<email><?php if(isset($entries[$i]['mail'][0])){ echo htmlspecialchars($entries[$i]['mail'][0]); } ?></email>
<phone><?php if(isset($entries[$i]['telephonenumber'][0])){ echo htmlspecialchars($entries[$i]['telephonenumber'][0]); } ?></phone>
<!-- Add custom elements here. Simply add them to $attrs above and then output the tag like the others here -->
</customer>
<?php endfor; ?>
</livelookup>
<?php ldap_unbind($ds); ?>

Storing MySQL Database connections in Array

When reviewing some of my existing code, I realized that I was constantly opening and close remote DB connections to pull information about hundreds of devices. I am now trying to resolve this by storing the database connections in an array and checking if the particular connection already exists by name before creating it.
$mysql_connections = array();
$devices = mysql_query("SELECT * FROM devices ORDER BY name ASC", $dp_conn);
while($row = mysql_fetch_array($devices))
{
$whmcs_site = $row['whmcs_site'];
$whmcs_id = $row['whmcs_id'];
/* WHMCS Service */
if ($whmcs_site != "" && $whmcs_id != "")
{
$site = get_site_details($whmcs_site, $dp_conn);
if (in_array($site['name'], $mysql_connections))
{
echo "Connection already exists</br>";
$whmcs = $mysql_connections[$site['name']];
}
else
{
echo "No connection exists...creating it named" . $site['name'] . " </br>";
$whmcs = whmcs_connect($site);
$mysql_connections[$site['name']] = $whmcs;
}
There are only 2 possible MySQL Databases so the in_array() check should be returning true after it stores both of them. For some reason it never finds the existing entries though so it continues to just spawn new connections on every iteration. Can anyone point out what the issue is here?
You need to check array_key_exists() or similar, not in_array() since you are comparing keys.

PHP mysql_fetch does not return values

Being quite new with PHP, I cannot find any solution why this does not work. The query is OK and the resource is returned. But I dunno why fetch_assoc does not print values. Thanks
$query=sprintf("SELECT ID,NAME FROM USERS WHERE PASS='%s' AND NAME='%s'",mysql_real_escape_string($p),mysql_real_escape_string($n));
$result=mysql_query($query);
if ($result)
{
while ($row = mysql_fetch_assoc($result)) {
echo $row['ID'];
echo $row['NAME'];
}
}
}
Some simple questions to start with:
Have you done a var_dump($row) to see what it returns?
Are you sure that the name and the password you specify are actually in the database?
Have you encrypted the password in the database (and not in the query)?
Have you a valid database connection ? (I know the answer is yes but a double check won't harm anyone and maybe save some headache)
Edit:
Added a link to the man page for var_dump.
As already suggested use mysql_error() to find what goes wrong. (A simple echo mysql_error(); after $result=mysql_query($query); will suffice)
write down out the query to see if something goes wrong with the escaping.
1.Echo out Your $query to see if it is what You like to be for debugging purposes;
2. Check $row['ID'] AND ['NAME'] if they are really UPPER letters;
3. Use mysql error reporting after if ($result){....} else { echo mysql_errno($link) . ": " . mysql_error($link) . "\n"; } where $link is Your DB handle.
Are you sure that rows were returned? You can use mysql_num_rows($result) to get the count. The only thing I can think of looking at your code is that you're passing in the password in plain text and the version in the DB is MD5 or something.

Categories