Random password generation awfulness

Modules, Add-ons and custom code that's more than just a quick hack or Mod.
Post Reply
Martin
Site Admin
Site Admin
Posts: 1854
Joined: Wed Jun 17, 2009 6:30 pm
Location: South Yorkshire UK
Contact:

Random password generation awfulness

Post by Martin »

Having had a number of customers complain that they can't remember their randomly generated passwords or locate the email that had it on... nor able to use a reset password function which also doesn't seem to work too well... I've opted to use a service from WebCogs to pull in a set of 10 random but English speech pronounceable passwords and then pick one at random using an MD5.

Small hiccup in that the WebCogs "instantly accessible" system doesn't like the generated key it sent me which, given my tired state, is a tad annoying, but anyway... I'll release the little module (it won't be hard to write :)) to anyone who wants to use it. You would obviously still need to buy your own access but I figure a small change like this might help reduce frustration levels with my customers and increase the chances of a repeat sale, instead of p*ssing them off. :)
CharlieFoxtrot
Confirmed
Confirmed
Posts: 413
Joined: Sun Aug 09, 2009 1:23 pm

Re: Random password generation awfulness

Post by CharlieFoxtrot »

Sometimes it seems that you're reading my mind! I was just pondering this issue the other day, and wondering if I could come up with something that would create a password using an internal array of pronouncable words.

I do not use the option that assigns passwords to customers who use guest-checkout... but from time to time I do have a customer who requests a new password via the forgotten password feature. It would be ideal if their new temporary password was something a bit more simple.

At the moment, this is a low priority enhancement for me... but if/when I get around to it, I'll share my code here.

Best,
Charlie
ISC 4.0.7

"... and let's be honest that whole "by design" thing is getting old too."
Martin
Site Admin
Site Admin
Posts: 1854
Joined: Wed Jun 17, 2009 6:30 pm
Location: South Yorkshire UK
Contact:

Re: Random password generation awfulness

Post by Martin »

I've discovered another reason to be stunned by the ISC code and prove to myself that there was little communication about what was available within the code within the team that actually developed various parts.

If you look in the lib/general.php code file you discover a function called GenerateReadablePassword()

This products a semi-reasonable password but for whatever reason the auto-generated password produced for guest checkouts just grabs an 8 digit md5 hash... I mean.. WTF?!! If there's something that can actually produce sensible passwords already in the code why the heck isn't the guest checkout making use of it?? The mind, it, how you say? Boggles!! :roll:

Anyway... my own code mod has been written after the support bod at webcogs sorted me out last night 5 minutes after I turned in for an early night... Can't fault their speed of service and the quick fix either...

I'll post up my code for using their service in due course.
Martin
Site Admin
Site Admin
Posts: 1854
Joined: Wed Jun 17, 2009 6:30 pm
Location: South Yorkshire UK
Contact:

Re: Random password generation awfulness

Post by Martin »

Grrr... I'm getting seriously [read: "annoyed"] with this code... It's written with duplication and comments that do not actually provide proper information as to what is going on.

Resetting a password with my module works but the guest account creation routine is completely ignoring the bit of code that indicates it was written for the task in the first place... FFS!
Martin
Site Admin
Site Admin
Posts: 1854
Joined: Wed Jun 17, 2009 6:30 pm
Location: South Yorkshire UK
Contact:

Re: Random password generation awfulness

Post by Martin »

Right... having finally figured out where, how, why it now makes a bit more sense as to why I was having problems locating the errant bit of code... Still somewhat annoying that the system doesn't make use of a single function to handle things but that's their issue.

It turns out that the system generates a customer account object in the $_SESSION array when it creates a pending order and associated billing address. TBH I have no idea why this is important when the actual auto-generated account isn't actually stored until the user reaches the "confirm order" point but that's the way it works.

Ok... here's the modification in rough, ready for me to write it up later properly...

Files:
  • /lib/general.php
  • /includes/classes/class.customer.php
  • /includes/classes/class.checkout.php
Open: /lib/general.php

5.x and earlier
Find:

Code: Select all

	function isIPAddress($ipaddr)
	{
		if (preg_match("#^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$#", $ipaddr, $digit)) {
			if (($digit[1] <= 255) && ($digit[2] <= 255) && ($digit[3] <= 255) && ($digit[4] <= 255)) {
				return true;
			}
		}

		return false;
	}
6.x and later
Find:

Code: Select all

	function canViewMobileSite()
	{
		$mobileDevice = getPortableDeviceType();
		if($mobileDevice && getConfig('enableMobileTemplate') && in_array($mobileDevice['device'], getConfig('enableMobileTemplateDevices'))) {
			return true;
		}

		return false;
	}
After, Add:

Code: Select all

	//MOD WebCogs Password Generator
	/*
	 * This mod gets a pronouncable password from the webcogs service 
	 * checks it and then uses it as the password for auto generated
	 * accounts.
	 * 
	 * Defaults back to the original ISC one if webcogs one is not available
	 *
	 */
	function webCogsPassword($type='') {
		
		
		$genpwd = '';
		
		// YOU NEED TO PUT YOUR WEBCOGS SERVICE SERIAL NUMBER BELOW
		$serial = "YOURSERIALHERE";
		// END EDITING.


		$url = "secure.webcogs.com";
		$path = "/webservices/";
		$file = "passwordgenerator.asmx/getRandomPassword?strAccessKey=";

		$filename = "http://".$url.$path.$file.$serial;

		$buffer = '';
		$dataFile = fopen( $filename, "r" ) ;
		if ( $dataFile ) {
			while (!feof($dataFile)) {
				$buffer .= fgets($dataFile, 4096);
			}
			fclose($dataFile);
		}
		else {
			return false;
		}

		// DEBUG echo $buffer;
	
		// Parse out the string suggested.
		$pattern = "@<string xmlns=\"(http|https){1}://".$url.$path."\">([a-z0-9]+)</string>@is";

		preg_match($pattern, $buffer, $matches);
		$genpwd = $matches[2];

		// Check the password is set and comprises alphanumerics of 5+ characters
		if(!preg_match("@[a-z0-9]{5,}@i", $genpwd)) {
			// empty the string if it does not
			$genpwd = '';
		}
		$password = (!empty($genpwd)) ? $genpwd : ($type=='read' ? GenerateReadablePassword(): substr(md5(uniqid(true)), 0, 8));
		
		return $password;
				
	}
	// MOD END WebCogs

Open: /includes/classes/class.customer.php

Find:

Code: Select all

				$password = GenerateReadablePassword();

				$updateData = array(
					'custpassword' => md5($password),
					'customerpasswordresettoken' => '',
					'customerpasswordresetemail' => '',
				);
BEFORE, Add:

Code: Select all

				//MOD WebCogs Password Generator
				$password = webCogsPassword('read');
				//$password = (!empty($genpwd)) ? $genpwd : GenerateReadablePassword();
				// MOD END WebCogs

Open: /includes/classes/class.checkout.php

Find:

Code: Select all

		// If we're automatically creating accounts for customers then we need to save those details too
		if(!CustomerIsSignedIn() && GetConfig('GuestCheckoutCreateAccounts')) {
AFTER, Add:

Code: Select all

			//MOD WebCogs Password Generator
			$password = webCogsPassword();
			// MOD END WebCogs
			
			//	$password = substr(md5(uniqid(true)), 0, 8);
Find:

Code: Select all

					$autoAccount = 1;
				}
				if(!isset($_SESSION['CHECKOUT']['CREATE_ACCOUNT']) && isset($_POST['billing_EmailAddress'])) {
BEFORE, Add:

Code: Select all

					//MOD WebCogs Password Generator
					$password = webCogsPassword();
					//$password = substr(md5(uniqid(true)), 0, 8);
					
					//DEBUG echo "\nPWD: $password"; exit;
					// MOD END WebCogs

Obviously take a backup of those files if you haven't already...

You will need to get a serial key from WebCogs for the password generator itself for £20 (+VAT if applicable)
Service info: http://www.webcogs.com/passwordgenerator/
Purchase Page: https://secure.webcogs.com/purchase.aspx?psid=27724


Doubtless, you could just use the GenerateReadablePassword() code that Interspire have neglected to use as their standard password generator but to be honest I prefer this solution even if it does rely on a third party service...

You'll notice that the code should also failover to use the local code if the service is unavailable. That side of things probably needs tweaking but as a version 1.0 it's not too shoddy...

Cheers
Post Reply