Solved

Need assistance with PHP passphrase strength checking and enforcement - passwdqc

Posted on 2010-11-18
9
977 Views
Last Modified: 2012-05-10
Hello,

I'm trying to implement a PHP "passphrase strength checking and enforcement" script called passwdqc and need some assistance getting it working.

The implementation is discussed on this page:
http://www.openwall.com/articles/PHP-Users-Passwords#enforcing-password-policy

Can someone provide some specific directions on how to get this to work?

I have the following (openwall.com-provided) code, pwqcheck.php as a 'required' script:
 
<?php

/*
 * The pwqcheck() function is a wrapper around the pwqcheck(1) program from
 * the passwdqc package:
 *
 * http://www.openwall.com/passwdqc/
 *
 * Returns 'OK' if the new password/passphrase passes the requirements.
 * Otherwise returns a message explaining one of the reasons why the
 * password/passphrase is rejected.
 *
 * $newpass and $oldpass are the new and current/old passwords/passphrases,
 * respectively.  Only $newpass is required.
 *
 * $user is the username.
 *
 * $aux may be the user's full name, e-mail address, and/or other textual
 * info specific to the user (multiple items may be separated with spaces).
 *
 * $args are additional arguments to pass to pwqcheck(1), to override the
 * default password policy.
 */
function pwqcheck($newpass, $oldpass = '', $user = '', $aux = '', $args = '')
{
// pwqcheck(1) itself returns the same message on internal error
	$retval = 'Bad passphrase (check failed)';

	$descriptorspec = array(
		0 => array('pipe', 'r'),
		1 => array('pipe', 'w'));
// Leave stderr (fd 2) pointing to where it is, likely to error_log

// Replace characters that would violate the protocol
	$newpass = strtr($newpass, "\n", '.');
	$oldpass = strtr($oldpass, "\n", '.');
	$user = strtr($user, "\n:", '..');

// Trigger a "too short" rather than "is the same" message in this special case
	if (!$newpass && !$oldpass)
		$oldpass = '.';

	if ($args)
		$args = ' ' . $args;
	if (!$user)
		$args = ' -2' . $args; // passwdqc 1.2.0+

	$command = 'exec '; // No need to keep the shell process around on Unix
	$command .= 'pwqcheck' . $args;
	if (!($process = @proc_open($command, $descriptorspec, $pipes)))
		return $retval;

	$err = 0;
	fwrite($pipes[0], "$newpass\n$oldpass\n") || $err = 1;
	if ($user)
		fwrite($pipes[0], "$user::::$aux:/:\n") || $err = 1;
	fclose($pipes[0]) || $err = 1;
	($output = stream_get_contents($pipes[1])) || $err = 1;
	fclose($pipes[1]);

	$status = proc_close($process);

// There must be a linefeed character at the end.  Remove it.
	if (substr($output, -1) === "\n")
		$output = substr($output, 0, -1);
	else
		$err = 1;

	if ($err === 0 && ($status === 0 || $output !== 'OK'))
		$retval = $output;

	return $retval;
}

?>

Open in new window


I have a form posting the username, password and a hidden variable to trigger the code to test a new password:
 
<form action="passwordtest.php" method="post" name="test">
Username: <input name="user" type="text">
<P>
Password <input name="newpass" type="text">
<input name="op" type="hidden" value="new"><br>
<input name="Submit" type="submit" value="submit">
</form>

Open in new window


Now, here... on the page that is catching the the form post and checking the password strength, is where things seem to break down. (Note: There also seems to be some extra code included from the article, for use if you are not using the pwqcheck script.) I've tried many different variations of all the code and the page either just ends up 'blank' or it throws an error complaining about an undefined fail() function.
 
<?php
require 'pwqcheck.php';
if ($_POST["user"]) {
$user=$_POST["user"];
}

if ($_POST["newpass"]) {
$newpass=$_POST["newpass"];
}

if ($_POST["op"]) {
$op=$_POST["op"];
}

// Do we have the pwqcheck(1) program from the passwdqc package?
$use_pwqcheck = TRUE;
// We can override the default password policy
$pwqcheck_args = '';
#$pwqcheck_args = 'config=/etc/passwdqc.conf';

function my_pwqcheck($newpass, $oldpass = '', $user = '')
{
	global $use_pwqcheck, $pwqcheck_args;
	if ($use_pwqcheck)
		return pwqcheck($newpass, $oldpass, $user, '', $pwqcheck_args);
		echo pwqcheck($newpass);
}

/* Some really trivial and obviously-insufficient password strength checks -
 * we ought to use the pwqcheck(1) program instead. */

	$check = '';
	if (strlen($newpass) < 7)
		$check = 'way too short';
	else if (stristr($oldpass, $newpass) ||
	    (strlen($oldpass) >= 4 && stristr($newpass, $oldpass)))
		$check = 'is based on the old one';
	else if (stristr($user, $newpass) ||
	    (strlen($user) >= 4 && stristr($newpass, $user)))
		$check = 'is based on the username';
	if ($check)
		return "Bad password ($check)";
	return 'OK';

if ($op === 'new') {
	if (($check = my_pwqcheck($pass, '', $user)) !== 'OK')
		fail($check);
		}
?>

Open in new window


I can't tell if the password is being accepted or rejected, so am unable to proceed with creating the rest of the page to enter the password into the DB or notify the user their password has been rejected.

Can someone please provide some specific insight into how to get this "passphrase strength checking and enforcement" script working?

Thanks!

Tom
0
Comment
Question by:PierceWeb
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
9 Comments
 
LVL 13

Expert Comment

by:dsmile
ID: 34170363
Problems're lying in this file passwordtest.php

1. Line 43: return "Bad password ($check)"; It causes your page to display blank when there's error.
2. Line 44: return 'OK';  It causes your page to display blank.
3. Line 47: fail($check) --> there's no such a function named fail(), that's why it gives you error.
It's really strange that you can see error on undefined function fail() because your script always ends at line 43 or 44.
0
 
LVL 13

Expert Comment

by:dsmile
ID: 34170387
Judge from your passwordtest.php file, I really don't know what you want to achieve.

If code from line 32 through 43 are supposed to be in function my_pwqcheck, and you just want to test whether this new function runs or not, then I modified it as below
<?php
require 'pwqcheck.php';

if ($_POST["user"]) {
$user=$_POST["user"];
}

if ($_POST["newpass"]) {
$newpass=$_POST["newpass"];
}

if ($_POST["op"]) {
$op=$_POST["op"];
}

// Do we have the pwqcheck(1) program from the passwdqc package?
$use_pwqcheck = TRUE;
// We can override the default password policy
$pwqcheck_args = '';
#$pwqcheck_args = 'config=/etc/passwdqc.conf';

function my_pwqcheck($newpass, $oldpass = '', $user = '')
{
        global $use_pwqcheck, $pwqcheck_args;
        if ($use_pwqcheck) {  //you should always use this brackets so that you won't be confused between logic
                return pwqcheck($newpass, $oldpass, $user, '', $pwqcheck_args);
		}

                //echo pwqcheck($newpass); //what is this anyway?

/* Some really trivial and obviously-insufficient password strength checks -
 * we ought to use the pwqcheck(1) program instead. */

        $check = '';
        if (strlen($newpass) < 7) {
                $check = 'way too short';
		}
        else if (stristr($oldpass, $newpass) ||
            (strlen($oldpass) >= 4 && stristr($newpass, $oldpass))) {
                $check = 'is based on the old one';
		}
        else if (stristr($user, $newpass) ||
            (strlen($user) >= 4 && stristr($newpass, $user))) {
                $check = 'is based on the username';
		}

        if ($check) {
                return "Bad password ($check)";
		}

        return 'OK';
}

if ($op === 'new') {
        if (($check = my_pwqcheck($newpass, '', $user)) !== 'OK') {
                //fail($check); //what is this again?
				die($check);
		}
}
?>

Open in new window

0
 
LVL 2

Author Comment

by:PierceWeb
ID: 34173592
Hi dsmile,

Thanks for your response. I won't be able to test the code you supplied until this evening, but I'll be sure to let you know what I find.

The passwordtest.php page is pretty much a regurgitation of the code I found in the cited article, as best I could determine. Here's the article URL:
http://www.openwall.com/articles/PHP-Users-Passwords#enforcing-password-policy

The goal is to build a new-user creation page that checks the strength of the user's password, prior to accepting it and inserting it into the database as part of their log-in credentials. The first step I am trying to accomplish is ensuring the new user has entered a STRONG password. Once I accomplish that, I'll be able to create the rest of what's needed.

Any additional advice I can test this evening is greatly appreciated.

Thanks!  Tom
0
Optimizing Cloud Backup for Low Bandwidth

With cloud storage prices going down a growing number of SMBs start to use it for backup storage. Unfortunately, business data volume rarely fits the average Internet speed. This article provides an overview of main Internet speed challenges and reveals backup best practices.

 
LVL 13

Expert Comment

by:dsmile
ID: 34174674
OK then.
My code in post 34170387 has already wrap it up for you as shown in your provided article.
I'll wait for your feedback :)
0
 
LVL 2

Author Comment

by:PierceWeb
ID: 34174702
Thanks dsmile.

I'll get back to you this evening.

I appreciate your assistance. Tom
0
 
LVL 2

Author Comment

by:PierceWeb
ID: 34177889
Hi dsmile,

I tried your code additions on the passwordtest.php page and it does return a result now. Unfortunately, no matter what password I enter into form it responds with "Bad passphrase (check failed)".

I'm not sure what it is, but something is still not working.

Do you have any ideas on what might make this entire script package work?

Thanks, Tom

0
 
LVL 13

Accepted Solution

by:
dsmile earned 500 total points
ID: 34180329
That message, Tom, is default message of pwqcheck() function

In the beginning of that php file, you can see these lines

/*
 * The pwqcheck() function is a wrapper around the pwqcheck(1) program from
 * the passwdqc package:
 *
 * http://www.openwall.com/passwdqc/
 *
 * Returns 'OK' if the new password/passphrase passes the requirements.
 * Otherwise returns a message explaining one of the reasons why the
 * password/passphrase is rejected.

So if you want to use pwqcheck(), you have to install passwdqc first.
I think these actions might be needed in order to get something right:
1. install passwdqc library and make sure it runs properly
2. run the php script again
3. debug the output case by case

I'm afraid I can only assist you this far, Tom
0
 
LVL 2

Author Comment

by:PierceWeb
ID: 34181433
Hi dsmile,

Thank you very much for your assistance.

I was under the impression that pwqcheck() could be used by accessing it via PHP. It looks like I won't be able to use the program then, as the site I wanted to use it on is hosted on a shared server and I don't have administrative rights to install pass the passwdqc module on the server.

Thanks again for your help!

Best regards,

Tom
0
 
LVL 2

Author Comment

by:PierceWeb
ID: 34181595
In the spirit of community, and to assist those who will come in search of a PHP script that can validate the strength of a password posted to it, below I have included a script I located and have done a slight bit of tweaking to. It still needs some work, but it's a good start.

Cheers!

Tom

 
<?php

$pwd = $_POST['pwd'];

if( strlen($pwd) < 8 ) {
	$error .= "Password too short! <br />";
}

if( strlen($pwd) > 20 ) {
	$error .= "Password too long! <br />";
}

if( !preg_match("#[0-9]+#", $pwd) ) {
	$error .= "Password must include at least one number! <br />";
}


if( !preg_match("#[a-z]+#", $pwd) ) {
	$error .= "Password must include at least one lowercase letter! <br />";
}


if( !preg_match("#[A-Z]+#", $pwd) ) {
	$error .= "Password must include at least one UPPERSCASE letter! <br />";
}



if( !preg_match("#\W+#", $pwd) ) {
	$error .= "Password must include at least one symbol! <br />";
}


if($error){
	echo "Password validation failure (password not strong enough): $error";
} else {
	echo "Your password passes our site requirements.";
}

?>

Open in new window

0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Many old projects have bad code, but the budget doesn't exist to rewrite the codebase. You can update this code to be safer by introducing contemporary input validation, sanitation, and safer database queries.
Did you know that more than 4 billion data records have been recorded as lost or stolen since 2013? It was a staggering number brought to our attention during last week’s ManageEngine webinar, where attendees received a comprehensive look at the ma…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

733 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question