Here is the patch file contents. This is only useful to users that know how to automatically apply a patch to source code.
Code:
Index: config.php
===================================================================
--- config.php (revision 12)
+++ config.php (working copy)
@@ -390,6 +390,14 @@
$START_CHAR_CODE = 100; # 'd' letter
#
+# Variables for MCrypt functionality, CRYPT_KEY should be changed per site
+#
+$CRYPT_KEY = 'YOUR_UNIQUE_SITE_KEY_HERE_ANY_NUMALPHA_KEY_MAKE_IT_LONG';
+$CRYPT_CIPHER = 'rijndael-256';
+$CRYPT_MODE = 'cbc';
+
+
+#
# Include functions
#
@include_once($xcart_dir."/include/func.php");
Index: include/change_password.php
===================================================================
--- include/change_password.php (revision 12)
+++ include/change_password.php (working copy)
@@ -95,7 +95,8 @@
$count = func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[old_passwords] WHERE login='".addslashes($xlogin)."' AND password='".addslashes(md5($old_password))."'");
if ($count<1)
db_query("INSERT INTO $sql_tbl[old_passwords] (login,password) VALUES ('".addslashes($xlogin)."','".addslashes(md5($old_password))."')");
- db_query("UPDATE $sql_tbl[customers] SET password='".addslashes(text_crypt($new_password))."', change_password='N' WHERE login='".addslashes($xlogin)."'");
+ $new_password = text_crypt($new_password,false,true,true);
+ db_query("UPDATE $sql_tbl[customers] SET password='".addslashes($new_password['s'])."', password_key='".addslashes($new_password['iv'])."', change_password='N' WHERE login='".addslashes($xlogin)."'");
if (isset($login_change["login"])) {
$login = $login_change["login"];
$login_type = $login_change["login_type"];
@@ -110,4 +111,4 @@
$location[] = array(func_get_langvar_by_name("lbl_chpass"), "");
-?>
+?>
\ No newline at end of file
Index: include/class.mcrypt.php
===================================================================
--- include/class.mcrypt.php (revision 0)
+++ include/class.mcrypt.php (revision 0)
@@ -0,0 +1,141 @@
+<?php
+
+/*
+ * class.mcrypt.php -> phpMcrypt Class (PHP4)
+ */
+
+/**
+ * @author Dustin Whittle
+ * @version 0.01
+ */
+
+if ( !defined('XCART_START') ) { header("Location: ../"); die("Access denied"); }
+
+class phpMcrypt
+{
+
+ var $td;
+ var $iv = false;
+
+ // this gets called when class is instantiated
+ function phpMcrypt($key = 'MyRandomStringThatWillAlwaysBeTheSame', $algorithm = 'tripledes', $mode = 'ecb', $iv = false)
+ {
+
+ if(extension_loaded('mcrypt') === FALSE)
+ {
+ $prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
+ dl($prefix . 'mcrypt.' . PHP_SHLIB_SUFFIX) or die('The Mcrypt module could not be loaded.');
+ }
+
+ // set mcrypt mode and cipher
+ $this->td = mcrypt_module_open($algorithm, '', $mode, '') ;
+
+ // Unix has better pseudo random number generator then mcrypt, so if it is available lets use it!
+ $random_seed = strstr(PHP_OS, "WIN") ? MCRYPT_RAND : MCRYPT_DEV_RANDOM;
+
+ // if initialization vector set in constructor use it else, generate from random seed
+ $this->iv = ($iv === false) ? mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), $random_seed) : substr($iv, 0, mcrypt_enc_get_iv_size($this->td));
+
+ // get the expected key size based on mode and cipher
+ $expected_key_size = mcrypt_enc_get_key_size($this->td);
+
+ // we dont need to know the real key, we just need to be able to confirm a hashed version
+ $key = substr(md5($key), 0, $expected_key_size);
+
+ // initialize mcrypt library with mode/cipher, encryption key, and random initialization vector
+ mcrypt_generic_init($this->td, $key, $this->iv);
+ }
+
+ function initvector()
+ {
+ /*
+ return the $iv used
+ */
+ return $this->iv;
+ }
+
+ function encrypt($plain_string)
+ {
+ /*
+ encrypt string using mcrypt and then encode any special characters
+ and then return the encrypted string
+ */
+ return base64_encode(mcrypt_generic($this->td, $plain_string));
+ }
+
+ function decrypt($encrypted_string)
+ {
+ /*
+ remove any special characters then decrypt string using mcrypt and then trim null padding
+ and then finally return the encrypted string
+ */
+ return trim(mdecrypt_generic($this->td, base64_decode($encrypted_string)));
+ }
+
+ // since php 4 does not have deconstructors, we will need to manually call this function
+ function __destruct()
+ {
+ // shutdown mcrypt
+ mcrypt_generic_deinit($this->td);
+
+ // close mcrypt cipher module
+ mcrypt_module_close($this->td);
+ }
+
+}
+
+/*** USAGE ***/
+/*
+require_once('include/class.mcrypt.php'); // require the phpMcrypt class
+
+$cryptKey = 'va364hqm34ha9v7v3n2aj3nvva6rl3m4nv78s64hv8d6cl2v4235h4';
+$cipher = 'rijndael-256';
+$mode = 'cbc';
+
+$crypto = new phpMcrypt($cryptKey, $cipher, $mode);
+$the_string_to_be_encrypted = 'blah.blah.blah';
+$the_string_that_is_encrypted = $crypto->encrypt($the_string_to_be_encrypted);
+$the_iv = $crypto->initvector();
+$crypto->__destruct();
+
+$crypto = new phpMcrypt($cryptKey, $cipher, $mode, $the_iv);
+$the_encrypted_string_decrypted = $crypto->decrypt($the_string_that_is_encrypted);
+$crypto->__destruct();
+
+echo 'Original: ' . $the_string_to_be_encrypted . '
';
+echo 'Initialization Vector: ' . $the_iv . '
';
+echo 'Encrypted: ' . $the_string_that_is_encrypted . '
';
+echo 'Decrypted: ' . $the_encrypted_string_decrypted . '
';
+*/
+
+/* Possible ciphers:
+cast-128
+gost
+rijndael-128
+twofish
+arcfour
+cast-256
+loki97
+rijndael-192
+saferplus
+wake
+blowfish-compat
+des
+rijndael-256
+serpent
+xtea
+blowfish
+enigma
+rc2
+tripledes
+*/
+
+/* Possible modes:
+CFB
+CBC // more secure than ECB, good security + speed compromise
+CTR
+ECB
+OFB
+*/
+
+?>
\ No newline at end of file
Index: include/func.php
===================================================================
--- include/func.php (revision 12)
+++ include/func.php (working copy)
@@ -447,24 +447,35 @@
return chr($START_CHAR_CODE + ($c & 240) / 16).chr($START_CHAR_CODE + ($c & 15));
}
-function text_crypt($s, $is_blowfish = false) {
- global $START_CHAR_CODE, $CRYPT_SALT, $merchant_password, $current_area, $active_modules, $blowfish, $config;
+function text_crypt($s, $is_blowfish = false, $ret_iv = false, $mcrypt = false) {
+ global $CRYPT_KEY, $CRYPT_CIPHER, $CRYPT_MODE, $START_CHAR_CODE, $CRYPT_SALT, $merchant_password, $current_area, $active_modules, $blowfish, $config, $xcart_dir;
if ($s == "")
return $s;
- if($is_blowfish && $merchant_password && ($current_area == 'A' || ($current_area == 'P' && $active_modules["Simple_Mode"])) && $blowfish && $config['Security']['blowfish_enabled'] == 'Y') {
- $s = trim($s);
- $result = "B".func_crc32($s).func_bf_crypt($s, $merchant_password);
- } else {
- $enc = rand(1,255); # generate random salt.
- $result = "S".text_crypt_symbol($enc); # include salt in the result;
- $enc ^= $CRYPT_SALT;
- for ($i = 0; $i < strlen($s); $i++) {
- $r = ord(substr($s, $i, 1)) ^ $enc++;
- if ($enc > 255)
- $enc = 0;
- $result .= text_crypt_symbol($r);
- }
+ if($mcrypt){
+ require_once($xcart_dir.'/include/class.mcrypt.php');
+
+ $crypto = new phpMcrypt($CRYPT_KEY, $CRYPT_CIPHER, $CRYPT_MODE);
+ $encrypted_str = $crypto->encrypt($s);
+ $iv = base64_encode($crypto->initvector());
+ $crypto->__destruct();
+
+ $result = $ret_iv?array('s'=>$encrypted_str,'iv'=>$iv):$encrypted_str;
+ }else{
+ if($is_blowfish && $merchant_password && ($current_area == 'A' || ($current_area == 'P' && $active_modules["Simple_Mode"])) && $blowfish && $config['Security']['blowfish_enabled'] == 'Y') {
+ $s = trim($s);
+ $result = "B".func_crc32($s).func_bf_crypt($s, $merchant_password);
+ } else {
+ $enc = rand(1,255); # generate random salt.
+ $result = "S".text_crypt_symbol($enc); # include salt in the result;
+ $enc ^= $CRYPT_SALT;
+ for ($i = 0; $i < strlen($s); $i++) {
+ $r = ord(substr($s, $i, 1)) ^ $enc++;
+ if ($enc > 255)
+ $enc = 0;
+ $result .= text_crypt_symbol($r);
+ }
+ }
}
return $result;
}
@@ -477,35 +488,48 @@
return (ord(substr($s, $i, 1)) - $START_CHAR_CODE)*16 + ord(substr($s, $i+1, 1)) - $START_CHAR_CODE;
}
-function text_decrypt($s) {
- global $START_CHAR_CODE, $CRYPT_SALT, $merchant_password, $current_area, $active_modules, $blowfish;
+function text_decrypt($s, $iv = '', $mcrypt = false) {
+ global $CRYPT_KEY, $CRYPT_CIPHER, $CRYPT_MODE, $START_CHAR_CODE, $CRYPT_SALT, $merchant_password, $current_area, $active_modules, $blowfish, $xcart_dir;
if ($s == "")
return $s;
- $crypt_method = substr($s, 0, 1);
- $s = substr($s, 1);
- if($crypt_method == 'B') {
- if($merchant_password && ($current_area == 'A' || ($current_area == 'P' && $active_modules["Simple_Mode"])) && $blowfish) {
- $crc32 = substr($s, 0, 4);
- $s = substr($s, 4);
- $result = func_bf_decrypt($s, $merchant_password);
- if(func_crc32($result) != $crc32) {
- $result = func_get_langvar_by_name('err_data_corrupted');
+ if($mcrypt){
+ require_once($xcart_dir.'/include/class.mcrypt.php');
+
+ if($iv!='')
+ $crypto = new phpMcrypt($CRYPT_KEY, $CRYPT_CIPHER, $CRYPT_MODE, base64_decode($iv));
+ else
+ $crypto = new phpMcrypt($CRYPT_KEY, $CRYPT_CIPHER, $CRYPT_MODE);
+ $decrypted_str = $crypto->decrypt($s);
+ $crypto->__destruct();
+
+ $result = $decrypted_str;
+ }else{
+ $crypt_method = substr($s, 0, 1);
+ $s = substr($s, 1);
+ if($crypt_method == 'B') {
+ if($merchant_password && ($current_area == 'A' || ($current_area == 'P' && $active_modules["Simple_Mode"])) && $blowfish) {
+ $crc32 = substr($s, 0, 4);
+ $s = substr($s, 4);
+ $result = func_bf_decrypt($s, $merchant_password);
+ if(func_crc32($result) != $crc32) {
+ $result = func_get_langvar_by_name('err_data_corrupted');
+ }
+ } else {
+ return false;
}
- } else {
- return false;
+ } elseif($crypt_method != 'B') {
+ if($crypt_method != 'S') {
+ $s = $crypt_method.$s;
+ }
+ $enc = $CRYPT_SALT ^ text_decrypt_symbol($s, 0);
+ $result = "";
+ for ($i = 2; $i < strlen($s); $i+=2) { # $i=2 to skip salt
+ $result .= chr(text_decrypt_symbol($s, $i) ^ $enc++);
+ if ($enc > 255)
+ $enc = 0;
+ }
}
- } elseif($crypt_method != 'B') {
- if($crypt_method != 'S') {
- $s = $crypt_method.$s;
- }
- $enc = $CRYPT_SALT ^ text_decrypt_symbol($s, 0);
- $result = "";
- for ($i = 2; $i < strlen($s); $i+=2) { # $i=2 to skip salt
- $result .= chr(text_decrypt_symbol($s, $i) ^ $enc++);
- if ($enc > 255)
- $enc = 0;
- }
}
return $result;
}
@@ -736,9 +760,9 @@
unset($extended_info);
}
- $userinfo["passwd1"] = stripslashes(text_decrypt($userinfo["password"]));
- $userinfo["passwd2"] = stripslashes(text_decrypt($userinfo["password"]));
- $userinfo["password"] = stripslashes(text_decrypt($userinfo["password"]));
+ $userinfo["passwd1"] = stripslashes(text_decrypt($userinfo["password"], $userinfo["password_key"], true));
+ $userinfo["passwd2"] = stripslashes(text_decrypt($userinfo["password"], $userinfo["password_key"], true));
+ $userinfo["password"] = stripslashes(text_decrypt($userinfo["password"], $userinfo["password_key"], true));
$userinfo["card_number"] = text_decrypt($userinfo["card_number"]);
list($userinfo["b_address"], $userinfo["b_address_2"]) = split("[\n\r]+", $userinfo["b_address"]);
$userinfo["b_statename"] = func_get_state($userinfo["b_state"], $userinfo["b_country"]);
@@ -5253,8 +5277,8 @@
#
# Check password security for specified user name
#
- $account = func_query_first("SELECT login, password FROM $sql_tbl[customers] WHERE login='$uname'");
- if ($account["login"] == text_decrypt($account["password"]))
+ $account = func_query_first("SELECT login, password, password_key FROM $sql_tbl[customers] WHERE login='$uname'");
+ if ($account["login"] == text_decrypt($account["password"], $account["password_key"], true))
$return[] = $account["login"];
}
else {
@@ -5265,9 +5289,9 @@
foreach ($accounts as $login_) {
if (!empty($uname) and $uname != $login_)
continue;
- $account = func_query_first("SELECT login, password FROM $sql_tbl[customers] WHERE login='$login_' AND usertype='$usertype'");
+ $account = func_query_first("SELECT login, password, password_key FROM $sql_tbl[customers] WHERE login='$login_' AND usertype='$usertype'");
if (!empty($account)) {
- if ($account["login"] == text_decrypt($account["password"]))
+ if ($account["login"] == text_decrypt($account["password"], $account["password_key"], true))
$return[] = $account["login"];
}
}
Index: include/help.php
===================================================================
--- include/help.php (revision 12)
+++ include/help.php (working copy)
@@ -135,14 +135,14 @@
#
if ($REQUEST_METHOD=="POST" and $action=="recover_password") {
-$accounts = func_query("select login, password, usertype from $sql_tbl[customers] where email='$email' and status='Y'");
+$accounts = func_query("select login, password, password_key, usertype from $sql_tbl[customers] where email='$email' and status='Y'");
#
# Decrypt passwords
#
if($accounts) {
foreach($accounts as $key=>$account)
- $accounts[$key]["password"]=text_decrypt($accounts[$key]["password"]);
+ $accounts[$key]["password"]=text_decrypt($accounts[$key]["password"], $accounts[$key]["password_key"], true);
$mail_smarty->assign("accounts",$accounts);
Index: include/login.php
===================================================================
--- include/login.php (revision 12)
+++ include/login.php (working copy)
@@ -95,7 +95,15 @@
$allow_login = in_array($REMOTE_ADDR, $iplist);
}
+
+ if ($user_data['password_key']==''){
+ $newpass = text_crypt(text_decrypt($user_data['password']),false,true,true);
+ $user_data['password'] = $newpass['s'];
+ $user_data['password_key'] = $newpass['iv'];
+ db_query("UPDATE $sql_tbl[customers] SET password='".addslashes($user_data["password"])."',password_key='".addslashes($user_data["password_key"])."' WHERE loginid='".$user_data["loginid"]."'");
+ unset($newpass);
+ }
- if (!empty($user_data) && $password == text_decrypt($user_data["password"]) && !empty($password) && $allow_login) {
+ if ($allow_login && !empty($user_data) && !empty($password) && $password == text_decrypt($user_data["password"], $user_data["password_key"], true)) {
#
# Success login
#
Index: include/register.php
===================================================================
--- include/register.php (revision 12)
+++ include/register.php (working copy)
@@ -341,7 +341,7 @@
#
# Fields filled without errors. User registered successfully
#
- $crypted = addslashes(text_crypt($passwd1));
+ $crypted = addslashes(text_crypt($passwd1,false,true,true));
if($default_fields['s_state']['avail'] == 'Y' && $default_fields['s_country']['avail'] == 'Y') {
if (is_array($states) and !func_check_state($states, stripslashes($s_state), $s_country) && $s_display_states) {
@@ -414,7 +414,7 @@
if ($mode=="update") {
$intershipper_recalc = "Y";
- db_query("UPDATE $sql_tbl[customers] SET password='$crypted', password_hint='$password_hint', password_hint_answer='$password_hint_answer', title='$title', firstname='$firstname', lastname='$lastname', company='$company', b_address='".$b_address."\n".$b_address_2."', b_city='$b_city', b_county='".(@$b_county)."', b_state='$b_state', b_country='$b_country', b_zipcode='$b_zipcode', s_address='".$s_address."\n".$s_address_2."', s_city='$s_city', s_county='".(@$s_county)."', s_state='$s_state', s_country='$s_country', s_zipcode='$s_zipcode', phone='$phone', email='$email', fax='$fax', url='$url', card_name='$card_name', card_type='$card_type', card_number='".addslashes(text_crypt($card_number))."', card_expire='$card_expire', card_cvv2='$card_cvv2', pending_membership='$pending_membership', ssn='$ssn', change_password='$change_password', parent = '$parent', pending_plan_id = '$pending_plan_id' WHERE login='$login' AND usertype='$login_type'");
+ db_query("UPDATE $sql_tbl[customers] SET password='".addslashes($crypted['s'])."', password_key='".addslashes($crypted['iv'])."', password_hint='$password_hint', password_hint_answer='$password_hint_answer', title='$title', firstname='$firstname', lastname='$lastname', company='$company', b_address='".$b_address."\n".$b_address_2."', b_city='$b_city', b_county='".(@$b_county)."', b_state='$b_state', b_country='$b_country', b_zipcode='$b_zipcode', s_address='".$s_address."\n".$s_address_2."', s_city='$s_city', s_county='".(@$s_county)."', s_state='$s_state', s_country='$s_country', s_zipcode='$s_zipcode', phone='$phone', email='$email', fax='$fax', url='$url', card_name='$card_name', card_type='$card_type', card_number='".addslashes(text_crypt($card_number))."', card_expire='$card_expire', card_cvv2='$card_cvv2', pending_membership='$pending_membership', ssn='$ssn', change_password='$change_password', parent = '$parent', pending_plan_id = '$pending_plan_id' WHERE login='$login' AND usertype='$login_type'");
db_query("DELETE FROM $sql_tbl[register_field_values] WHERE login = '$login'");
if($additional_values) {
@@ -467,7 +467,7 @@
#
$intershipper_recalc = "Y";
- db_query("INSERT INTO $sql_tbl[customers] (login,usertype,password,password_hint,password_hint_answer,title,firstname,lastname,company,b_address,b_city,b_county,b_state,b_country,b_zipcode,s_address,s_city,s_county,s_state,s_country,s_zipcode,phone,email,fax,url,card_name,card_type,card_number,card_expire,card_cvv2,first_login,status,referer,pending_membership,ssn,parent,pending_plan_id,change_password) VALUES ('$uname','$usertype','$crypted','".@$password_hint."','".@$password_hint_answer."','$title','$firstname','$lastname','$company','".$b_address."\n".$b_address_2."','$b_city','".(@$b_county)."','$b_state','$b_country','$b_zipcode','".$s_address."\n".$s_address_2."','$s_city','".(@$s_county)."','$s_state','$s_country','$s_zipcode','$phone','$email','$fax','$url','".@$card_name."','".@$card_type."','".addslashes(text_crypt(@$card_number))."','".@$card_expire."','".@$card_cvv2."','".time()."','Y','".@$RefererCookie."','".@$pending_membership."','".@$ssn."', '$parent', '$pending_plan_id','$change_password')");
+ db_query("INSERT INTO $sql_tbl[customers] (login,usertype,password,password_key,password_hint,password_hint_answer,title,firstname,lastname,company,b_address,b_city,b_county,b_state,b_country,b_zipcode,s_address,s_city,s_county,s_state,s_country,s_zipcode,phone,email,fax,url,card_name,card_type,card_number,card_expire,card_cvv2,first_login,status,referer,pending_membership,ssn,parent,pending_plan_id,change_password) VALUES ('$uname','$usertype','".addslashes($crypted['s'])."','".addslashes($crypted['iv'])."','".@$password_hint."','".@$password_hint_answer."','$title','$firstname','$lastname','$company','".$b_address."\n".$b_address_2."','$b_city','".(@$b_county)."','$b_state','$b_country','$b_zipcode','".$s_address."\n".$s_address_2."','$s_city','".(@$s_county)."','$s_state','$s_country','$s_zipcode','$phone','$email','$fax','$url','".@$card_name."','".@$card_type."','".addslashes(text_crypt(@$card_number))."','".@$card_expire."','".@$card_cvv2."','".time()."','Y','".@$RefererCookie."','".@$pending_membership."','".@$ssn."', '$parent', '$pending_plan_id','$change_password')");
db_query("REPLACE INTO $sql_tbl[login_history] (login, date_time, usertype, action, status, ip) VALUES ('$uname','".time()."','$usertype','login','success','$REMOTE_ADDR')");
Index: sql/xcart_tables.sql
===================================================================
--- sql/xcart_tables.sql (revision 12)
+++ sql/xcart_tables.sql (working copy)
@@ -281,7 +281,8 @@
login varchar(32) NOT NULL default '',
usertype char(1) NOT NULL default '',
membership varchar(32) NOT NULL default '',
- password varchar(128) NOT NULL default '',
+ password blob NOT NULL,
+ password_key blob NOT NULL,
password_hint varchar(128) NOT NULL default '',
password_hint_answer varchar(128) NOT NULL default '',
b_address varchar(64) NOT NULL default '',