Page 2 of 7

Re: Mixing php and html

Posted: Fri Mar 16, 2012 9:46 pm
by Pavilion
Sorry Celauran:

My head is swimming with questions, so much so that sometimes I forget the basics. The following code came with the PHPass demos -

Code: Select all

<?php

require '../PasswordHash.php';

// In a real application, these should be in a config file instead
$db_host = '127.0.0.1';
$db_port = 3306;
$db_user = 'mydbuser';
$db_pass = 'voulDyu0gue$s?';
$db_name = 'myapp';

// Base-2 logarithm of the iteration count used for password stretching
$hash_cost_log2 = 8;
// Do we require the hashes to be portable to older systems (less secure)?
$hash_portable = FALSE;

// Are we debugging this code?  If enabled, OK to leak server setup details.
$debug = TRUE;

function fail($pub, $pvt = '')
{
	global $debug;
	$msg = $pub;
	if ($debug && $pvt !== '')
		$msg .= ": $pvt";
/* The $pvt debugging messages may contain characters that would need to be
 * quoted if we were producing HTML output, like we would be in a real app,
 * but we're using text/plain here.  Also, $debug is meant to be disabled on
 * a "production install" to avoid leaking server setup details. */
	exit("An error occurred ($msg).\n");
}

function get_post_var($var)
{
	$val = $_POST[$var];
	if (get_magic_quotes_gpc())
		$val = stripslashes($val);
	return $val;
}

header('Content-Type: text/plain');

$op = $_POST['op'];
if ($op !== 'new' && $op !== 'login')
	fail('Unknown request');

$user = get_post_var('user');
/* Sanity-check the username, don't rely on our use of prepared statements
 * alone to prevent attacks on the SQL server via malicious usernames. */
if (!preg_match('/^[a-zA-Z0-9_]{1,60}$/', $user))
	fail('Invalid username');

$pass = get_post_var('pass');
/* Don't let them spend more of our CPU time than we were willing to.
 * Besides, bcrypt happens to use the first 72 characters only anyway. */
if (strlen($pass) > 72)
	fail('The supplied password is too long');

$db = new mysqli($db_host, $db_user, $db_pass, $db_name, $db_port);
if (mysqli_connect_errno())
	fail('MySQL connect', mysqli_connect_error());

$hasher = new PasswordHash($hash_cost_log2, $hash_portable);

if ($op === 'new') {
	$hash = $hasher->HashPassword($pass);
	if (strlen($hash) < 20)
		fail('Failed to hash new password');
	unset($hasher);

	($stmt = $db->prepare('insert into users (user, pass) values (?, ?)'))
		|| fail('MySQL prepare', $db->error);
	$stmt->bind_param('ss', $user, $hash)
		|| fail('MySQL bind_param', $db->error);
	if (!$stmt->execute()) {
/* Figure out why this failed - maybe the username is already taken?
 * It could be more reliable/portable to issue a SELECT query here.  We would
 * definitely need to do that (or at least include code to do it) if we were
 * supporting multiple kinds of database backends, not just MySQL.  However,
 * the prepared statements interface we're using is MySQL-specific anyway. */
		if ($db->errno === 1062 /* ER_DUP_ENTRY */)
			fail('This username is already taken');
		else
			fail('MySQL execute', $db->error);
	}

	$what = 'User created';
} else {
	$hash = '*'; // In case the user is not found
	($stmt = $db->prepare('select pass from users where user=?'))
		|| fail('MySQL prepare', $db->error);
	$stmt->bind_param('s', $user)
		|| fail('MySQL bind_param', $db->error);
	$stmt->execute()
		|| fail('MySQL execute', $db->error);
	$stmt->bind_result($hash)
		|| fail('MySQL bind_result', $db->error);
	if (!$stmt->fetch() && $db->errno)
		fail('MySQL fetch', $db->error);

	if ($hasher->CheckPassword($pass, $hash)) {
		$what = 'Authentication succeeded';
	} else {
		$what = 'Authentication failed';
	}
	unset($hasher);
}

$stmt->close();
$db->close();

echo "$what\n";

?>
Hope this clears things up as to where the code is coming from.

Pavilion

Re: Mixing php and html

Posted: Sat Mar 17, 2012 5:28 am
by Celauran
Huh. Not with anything I've downloaded. That aside, look at this:

Code: Select all

<?php

require 'PasswordHash.php';

# Try to use stronger but system-specific hashes, with a possible fallback to
# the weaker portable hashes.
$t_hasher = new PasswordHash(8, FALSE);

$correct = 'test12345';
$hash = $t_hasher->HashPassword($correct);

print 'Hash: ' . $hash . "<br />";

$check = $t_hasher->CheckPassword($correct, $hash);
print "Check correct: '" . $check . "' (should be '1')<br />";

$wrong = 'test12346';
$check = $t_hasher->CheckPassword($wrong, $hash);
print "Check wrong: '" . $check . "' (should be '0' or '')<br />";

Re: Mixing php and html

Posted: Sat Mar 17, 2012 7:10 am
by Pavilion
Hello Celauran:

I tried your test. It has been added to the register.php and works just fine. I was able to register and activate my account.

However when I attempt to login I get the following messages:
Hash: $P$BXZ0Tg5t3b3uCj5Vm3MiDa9w1CkKLo1
Check correct: '1' (should be '1')
Check wrong: '1' (should be '0' or '')
Either Your Account is inactive or Email address /Password is Incorrect
string(146) "SELECT * FROM UserTbl WHERE (EmailAddress='####@####.com' AND Password='$P$BXZ0Tg5t3b3uCj5Vm3MiDa9w1CkKLo1') AND Activation IS NULL"


The Hash result does NOT equal the password hash stored in my table.

Following is the login.php script (I know it's messy - but I am really lost here).

Code: Select all

<?php
// include database connection file, if connection doesn't work the include file will throw an error message
include '../schedule/include/db_connect.php';

// including PasswordHash file for purposes of hashing password submission.
require '../PasswordHash.php';

if (isset($_POST['formsubmitted'])) {
 // Initialize a session:
session_start();
 $error = array();//this aaray will store all error messages

 if (empty($_POST['email'])) {//if the email supplied is empty
 $error[] = 'You forgot to enter  your Email ';
 } else {

if (isset($_POST['email']) && filter_var($_POST['email'], FILTER_VALIDATE_EMAIL))
{
    // If you're putting it in a query, escape it.
    $email = mysql_real_escape_string($_POST['email']);
}
else {
 $error[] = 'Your EMail Address is invalid  ';
 }
}

if (empty($_POST['Password'])) {
 $error[] = 'Please Enter Your Password ';
 } else {
 $password = $_POST['Password'];
 }
 
 // test script from Celauran
# Try to use stronger but system-specific hashes, with a possible fallback to
# the weaker portable hashes.
$t_hasher = new PasswordHash(8, FALSE);

$correct = $password;
$hash = $t_hasher->HashPassword($correct);
print 'Hash: ' . $hash . "<br />";

$check = $t_hasher->CheckPassword($correct, $hash);
print "Check correct: '" . $check . "' (should be '1')
";

$wrong = $password;
$check = $t_hasher->CheckPassword($wrong, $hash);
print "Check wrong: '" . $check . "' (should be '0' or '')
";

// end test script from Celauran
        unset($hasher);

 if (empty($error))//if the array is empty , it means no error found
 {
$query_check_credentials = "SELECT * FROM UserTbl WHERE (EmailAddress='$email' AND Password='$hash') AND Activation IS NULL";
 $result_check_credentials = mysql_query($query_check_credentials, $link);
 if(!$result_check_credentials){//If the QUery Failed
 echo 'Query Failed ';
 }

 if (@mysql_num_rows($result_check_credentials) == 1)//if Query is successfull
 { // A match was made.

 $_SESSION = mysql_fetch_array($result_check_credentials, MYSQLI_ASSOC);

//Assign the result of this query to SESSION Global Variable

 header("Location: page.php");

 }else
 { $msg_error= 'Either Your Account is inactive or Email address /Password is Incorrect';
 }
}  else {
 echo '<div> <ol>';
 foreach ($error as $key => $values) {
 echo '    <li>'.$values.'</li>';
}
 echo '</ol></div>';
}
 if(isset($msg_error)){
 echo '<div>'.$msg_error.' </div>';
 }
 mysql_close($link);
} // End of the main Submit conditional

// find errors manually -
var_dump($query_check_credentials);
?>
<!DOCTYPE html>
<html>
<form action="login.php" method="post">
 <fieldset>
 <legend>Login Form  </legend>

 

Enter Your username and Password Below  


 <div>
 bel for="name">Email :bel>
 <input type="email" id="email" name="email" size="25" />
 </div>

 <div>
 bel for="Password">Password:bel>
 <input type="password" id="Password" name="Password" size="25" />
 </div>
 <div>
 <input type="hidden" name="formsubmitted" value="TRUE" />
 <input type="submit" value="Login" />
 </div>
 </fieldset>
</form>
</html>

Thank you for you patience - Pavilion

Re: Mixing php and html

Posted: Sat Mar 17, 2012 9:47 am
by Celauran
You need to select the hash from the database, then pass it and the user-submitted password to CheckPassword().

Re: Mixing php and html

Posted: Sat Mar 17, 2012 11:06 am
by Pavilion
Celauran wrote:You need to select the hash from the database, then pass it and the user-submitted password to CheckPassword().
OK - just checking here - because I am at a total loss.

When passing the user-submitted password to CheckPassword(), I don't have to hash it before passing it????

So then I'd
  1. apply a variable to the hash stored in the database
  2. apply a variable to the user-submitted password
  3. And pass them both to CheckPassword, with the user-submitted password 1st in order?

Re: Mixing php and html

Posted: Sat Mar 17, 2012 11:18 am
by Celauran
That's right. You'll need to remove the password bit from the WHERE clause of your query, obviously.

Re: Mixing php and html

Posted: Sat Mar 17, 2012 11:34 am
by Pavilion
Celauran wrote:That's right. You'll need to remove the password bit from the WHERE clause of your query, obviously.
OK - now I'm starting to get a grasp on this. I don't understand how check password() works if I'm throwing a text submitted password and a stored hash together, but I can let that go for now.

Yes - I'd already thought about removing the password bit from the WHERE clause. Logic would also dictate, that if CheckPassword comes back "wrong" then I don't allow the code to execute any further. So the MySql query would never even run, if CheckPassword comes back wrong.

I'm taking it CheckPassword returns a 1 or a 0. If it returns a 1 then all is well, if it returns a 0 then don't execute code any further?

Re: Mixing php and html

Posted: Sat Mar 17, 2012 12:07 pm
by Celauran
Also right. You have to execute one query regardless, though; you still need to get the hashed password for the username in question.

Re: Mixing php and html

Posted: Sat Mar 17, 2012 12:14 pm
by Pavilion
Celauran wrote:Also right. You have to execute one query regardless, though; you still need to get the hashed password for the username in question.
Yes - I'm working on that now. Probably a very simple thing for you... but I'm doing the baby step waltz. (sigh)...

Re: Mixing php and html

Posted: Mon Mar 19, 2012 10:19 pm
by Pavilion
OK - Celauran:

The Baby Step waltz has yielded some results. The code for login.php follows:

I fully expect to clean it up - but it's letting me in when the login submission is valid and it's keeping me out when the login submission is not valid.

Code: Select all

<?php
// include database connection file, if connection doesn't work the include file will throw an error message
include '../schedule/include/db_connect.php';

// including PasswordHash file for purposes of hashing password submission.
require '../PasswordHash.php';

// Initialize a session:
if (isset($_POST['formsubmitted'])) {
session_start();


// Error handling routine. Declare an Array to store any error message. As php process the following "if" statement, true results are added to the $errors array. $errors echo with php script in the html form.
$errors = array();
if (!empty($_POST)) // If NOT empty $_POST - exclamation point is "not" in php.
{
    $email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
    if (!$email)
    {
        $errors['email'] = "Not a valid email address.";
    }
    else
    {
		// assign variable to user submitted email.
		$email = mysql_real_escape_string(trim($_POST['email']));
    }
	if (!$_POST['password'])
	{
        $errors['password'] = "Password cannot be empty.";
	}
	else
	{
		// assign variable to user submitted password.
		$password = mysql_real_escape_string(trim($_POST['password']));
 
		// find table password
		$find_table_pass = 
		"SELECT UserTbl.EmailAddress, UserTbl.Password, UserTbl.Activation, UserTbl.user_id
		FROM UserTbl
		WHERE (EmailAddress='$email') AND Activation IS NULL";

		// this is the mysql_query call. No data will be passed from the table without this call.
		$result = mysql_query($find_table_pass, $link);

		// fetch array gathers data from the table
		while($row = mysql_fetch_array($result))
		{
		$table_pass = $row['Password']; // assign variable to table password.
		$table_userid = $row['user_id']; // assign variable to user id for session variable.
 	
		// test script from Celauran
		# Try to use stronger but system-specific hashes, with a possible fallback to
		# the weaker portable hashes.

		$t_hasher = new PasswordHash(8, FALSE); //for some reason this line is needed. I believe it assists CheckPassword() in some way.

		$check = $t_hasher->CheckPassword($password, $table_pass);
		// Test is returning a '1' - it is successful. You've successfully matched email address and password.
		// end test script from Celauran
		// unset($hasher); // is this line necessary?
		
		echo "this is the check result: " . $check . "<br />";
			
		if ($check==1)
		{
			echo "You're in - Congratulations!";
			$_SESSION = $table_userid; // the reason I assigned user_id to $_SESSION is that I'll need that value for inserting data into tables throughout the application.
			echo "Session variable: " . $_SESSION;
		}
			else
		{
			echo 'Please double-check your email &/or password submissions.';
		}
		} // While block ends here.
	}

 }
  mysql_close($link);
} // End of the main Submit conditional

?>
<!DOCTYPE html>
<html>
<form action="login.php" method="post">
 <fieldset>
 <legend>Login Form  </legend>

 <p>Enter Your username and Password Below  </p>

 <div>
 <label for="name">Email :</label>
 <input type="email" id="email" name="email" size="25" />
 </div>

 <div>
 <label for="Password">Password:</label>
 <input type="password" id="password" name="password" size="25" />
 </div>
 <div>
 <input type="hidden" name="formsubmitted" value="TRUE" />
 <input type="submit" value="Login" />
 </div>
 </fieldset>
	<?php if (isset($errors['password'])):?>
	<li><?php echo $errors['password']; ?></li>
	<?php endif; ?>
	
	<?php if (isset($errors['email'])): ?>
	<li><?php echo $errors['email']; ?></li>
	<?php endif; ?>

	<?php if (isset($denied)): ?>
	<p class="borderbx"><?php echo $denied; ?></p>
	<?php endif; ?>
</form>
</html>
I honestly look forward to your feedback -

Pavilion

Re: Mixing php and html

Posted: Tue Mar 20, 2012 5:32 am
by Celauran
Looks good. You've omitted <head> and <body> tags in your HTML. The only other thing I noticed is that you're assigning the user ID directly to $_SESSION. $_SESSION is an array, you assigning it to $_SESSION['userid'] would make more sense.

Re: Mixing php and html

Posted: Tue Mar 20, 2012 8:48 pm
by Pavilion
Celauran wrote:Looks good. You've omitted <head> and <body> tags in your HTML. The only other thing I noticed is that you're assigning the user ID directly to $_SESSION. $_SESSION is an array, you assigning it to $_SESSION['userid'] would make more sense.
Celauran - WOW - you can not imagine how happy your comments have made me. I fully expected to make a lot of corrections. About the corrections you have noted:
  1. You mentioned missing <head> and <body> tags. I will definitely add those... but your comments brought something else to my mind. When declaring an HTML Doc Type, what type do I declare? Research shows that there are many doc types and it all confuses me. The register.php file we worked on earlier looks very different when using the IE browser. I assume this has something to do with the DocType declaration?
  2. About the $_SESSION variable, after submitting my last post I did figure out it is possible to declare an array with the $_SESSION variable. This makes sense, because if one has to consistently access the same table (UserTbl), then assigning a $_SESSION variable array to this table makes sense. But, if I assign an array to $_SESSION, is there a way to also assign a global variable to $row['user_id']?
  3. Also, if I assign an array to $_SESSION, then can I also query another table and set other arrays within page actions? For instance, if I want users to insert data into another table, can I write INSERT or SELECT queries on this other table and get arrays from those queries?
Thanks - Pavilion

Re: Mixing php and html

Posted: Tue Mar 20, 2012 9:03 pm
by Celauran
Pavilion wrote:You mentioned missing <head> and <body> tags. I will definitely add those... but your comments brought something else to my mind. When declaring an HTML Doc Type, what type do I declare? Research shows that there are many doc types and it all confuses me. The register.php file we worked on earlier looks very different when using the IE browser. I assume this has something to do with the DocType declaration?
That has more to do with IE than anything. You get used to that. IE doesn't support HTML5, pretty much every standards-compliant browser does. Still, as IE still has significant "market share" (for lack of a better term), you had best support it. That said, XHTML 1.0 Strict is a good bet.
Pavilion wrote:About the $_SESSION variable, after submitting my last post I did figure out it is possible to declare an array with the $_SESSION variable. This makes sense, because if one has to consistently access the same table (UserTbl), then assigning a $_SESSION variable array to this table makes sense. But, if I assign an array to $_SESSION, is there a way to also assign a global variable to $row['user_id']?
I wasn't so much talking about assigning an array to the $_SESSION variable as I was pointing out that the $_SESSION variable is an array. Storing a user's ID in the $_SESSION array is common practice and a good way to keep track of your logged-in users.
Pavilion wrote:Also, if I assign an array to $_SESSION, then can I also query another table and set other arrays within page actions? For instance, if I want users to insert data into another table, can I write INSERT or SELECT queries on this other table and get arrays from those queries?
I'm not quite sure what you mean here. Can you provide a more specific/detailed example?

Re: Mixing php and html

Posted: Wed Mar 21, 2012 12:34 pm
by thinsoldier
Celauran wrote:You're still checking for $_GET['email'] instead of $_POST['email']
This is the #1 most annoying thing to me. Now I always start my scripts with:

Code: Select all

$_input = $_POST;
// or $input = $_GET;
//and just use $_input['foobar']; throughout the code. 
// If I change my mind I just change 1 line of code to use GET instead.

Re: Mixing php and html

Posted: Wed Mar 21, 2012 12:49 pm
by thinsoldier
Celauran wrote:
Pavilion wrote:You mentioned missing <head> and <body> tags. I will definitely add those... but your comments brought something else to my mind. When declaring an HTML Doc Type, what type do I declare? Research shows that there are many doc types and it all confuses me. The register.php file we worked on earlier looks very different when using the IE browser. I assume this has something to do with the DocType declaration?
That has more to do with IE than anything. You get used to that. IE doesn't support HTML5, pretty much every standards-compliant browser does. Still, as IE still has significant "market share" (for lack of a better term), you had best support it. That said, XHTML 1.0 Strict is a good bet.
Actually XHTML is not what should be used. If you're not sending xml headers along with that doctype the browser is really just interpreting it as tag soup. If you do send the xml headers IE will treat it as proper xml/xhtml and kill the entire page IF there's even the slightest syntax error in your markup.

Use the HTML5 doctype: <!DOCTYPE html>
Yes IE 6,7,8 & 9 lack many features from HTML5 and its related technologies (javascript, css3, etc) But they do switch to their most standards compliant rendering mode when they encounter the HTML5 doctype and that's really what the doctype is used for.

http://adactio.com/journal/1595/
http://tantek.com/2010/302/b1/xhtml-dea ... alid-html5

Also the quantity and quality of support for all of html5 and all of its related APIs across all browsers is still pretty poor. About the only thing that's 100% usable is the html5 doctype for triggering the best css rendering mode and most of css 2 and 3.