[sork] Vpopmail + Mysql + Passwd + Crypt md5 Fix Summary
Ashvin Babu / Surya Technologi
a32aw11sc at yahoo.com
Wed Nov 26 00:59:04 PST 2003
Here is a summary of this fix. All this information
was found in the archives, but I thought it would be
useful to include it in one summary post.
I am using the latest stable Horde/IMP and this
version of passwd:
passwd-RELENG-2003-11-25.tar.gz (latest snapshot)
I am also using vpopmail/qmail/mysql.
To get passwd to work, these are the backend file
settings for vpopmail:
$backends['vpopmail'] = array (
'name' => 'vpopmail Authentication',
'preferred' => '',
'password policy' => array(
'minLength' => 3,
'maxLength' => 8,
'maxSpace' => 0,
'minUpper' => 0,
'minLower' => 0,
'minNumeric' => 0
),
'driver' => 'vpopmail',
'params' => array(
'phptype' => 'mysql',
'hostspec' => 'localhost',
'username' => 'your mysql username',
'password' => 'your mysql password',
'encryption' => 'crypt-md5',
'database' => 'vpopmail',
'table' => 'table name for your domain',
'name' => 'pw_name',
'domain' => 'pw_domain',
'passwd' => 'pw_passwd',
'clear_passwd' => 'pw_clear_passwd',
'use_clear_passwd' => 'true',
'socket' => '/var/lib/mysql.sock',
'protocol' => 'tcp'
)
);
The Crypt-md5 patch for Driver.php is posted here:
http://lists.horde.org/archives/sork/Week-of-Mon-20030324/000887.html
I have tried to attach the modified Driver.php to this
posting (don't know if we can attach files).
You also have to modify your mysql database to add the
pw_domain field (then populate the field with your
domain name). I have a standard vpopmail/mysql install
and it was missing this field:
Database changed
mysql> ALTER TABLE suryatechnologies_com ADD COLUMN
pw_domain varchar(100
);
Query OK, 9 rows affected (0.03 sec)
Records: 9 Duplicates: 0 Warnings: 0
mysql> UPDATE suryatechnologies_com SET
pw_domain='suryatechnologies.com'
-> ;
Query OK, 9 rows affected (0.01 sec)
Rows matched: 9 Changed: 9 Warnings: 0
mysql>
Thanks to everyone on this list who created the above
information. It is good to have password finally
working with vpopmail/mysql.
Ashvin / suryatechnologies.com
__________________________________
Do you Yahoo!?
Free Pop-Up Blocker - Get it now
http://companion.yahoo.com/
-------------- next part --------------
<?php
/**
* $Horde: passwd/lib/Driver.php,v 1.3.2.6 2003/02/15 20:16:26 ericr Exp $
*
* Passwd_Driver:: defines an API for implementing password change
* systems for Passwd.
*
* @author Mike Cochrane <mike at graftonhall.co.nz>
* @author Eric Rostetter <eric.rostetter at physics.utexas.edu>
* @version $Revision: 1.3.2.6 $
* @since Passwd 2.1
* @package passwd
*/
class Passwd_Driver {
/** error string returned to user if an eror occurs. */
var $err_str;
/**
* Attempts to return a concrete Passwd_Driver instance based on $driver.
*
* @param string $driver The type of concrete passwd_Driver subclass
* to return. The is based on the passwd
* driver ($driver). The code is dynamically
* included.
*
* @param array $params (optional) A hash containing any additional
* configuration or connection parameters a
* subclass might need.
*
* @return mixed The newly created concrete Passwd_Driver instance, or
* false on an error.
*/
function &factory($driver, $params = array())
{
$driver = strtolower(basename($driver));
@include_once dirname(__FILE__) . '/Driver/' . $driver . '.php';
$class = 'Passwd_Driver_' . $driver;
if (class_exists($class)) {
return new $class($params);
} else {
return false;
}
}
/**
* Attempts to return a reference to a concrete Passwd_Driver instance
* based on $driver. It will only create a new instance if no
* Passwd_Driver instance with the same parameters currently exists.
*
* This should be used if multiple storage sources are required.
*
* This method must be invoked as: $var = &Passwd_Driver::singleton()
*
* @param string $driver The type of concrete Passwd_Driver subclass
* to return. The is based on the passwd
* driver ($driver). The code is dynamically
* included.
*
* @param array $params (optional) A hash containing any additional
* configuration or connection parameters a
* subclass might need.
*
* @return mixed The created concrete Passwd_Driver instance, or false
* on error.
*/
function &singleton($driver, $params = array())
{
static $instances;
if (!isset($instances)) {
$instances = array();
}
$signature = serialize(array($driver, $params));
if (!isset($instances[$signature])) {
$instances[$signature] = &Passwd_Driver::factory($driver, $params);
}
return $instances[$signature];
}
/**
* Compare a plaintext password with an encrypted password.
*
* @return Boolean True is they match, False if they differ
*/
function comparePasswords($encrypted, $plaintext)
{
switch ($this->_params['encryption']) {
case "plain":
if ($encrypted == $plaintext) {
return true;
}
break;
case 'md5-hex':
if ($encrypted == md5($plaintext)) {
return true;
}
break;
case 'md5-base64':
if ($encrypted == base64_encode(mHash(MHASH_MD5, $plaintext))) { return true;
}
break;
case 'crypt-md5':
$salt = substr($encrypted , 0, 8);
if ($encrypted == crypt($plaintext, $salt)) {
return true;
}
break;
case 'crypt':
$encrypted = substr($encrypted, 7);
$salt = substr($encrypted , 0, 2);
if ($encrypted == crypt($plaintext, $salt)) {
return true;
}
break;
case 'sha':
$encrypted = substr($encrypted, 5);
if ($encrypted == base64_encode(mHash(MHASH_SHA1, $plaintext)))
{
return true;
}
break;
case 'ssha':
$encrypted = substr($encrypted, 6);
$hash = base64_decode($encrypted);
$salt = substr($hash, 20);
if ($hash == mHash(MHASH_SHA1, $plaintext . $salt)) {
return true;
}
break;
case 'smd5':
$encrypted = substr($encrypted, 6);
$hash = base64_decode($encrypted);
$salt = substr($hash, 16);
if ($hash == mHash(MHASH_MD5, $plaintext . $salt)) {
return true;
}
break;
default:
return PEAR::raiseError($this->_params['encryption'] . ' Encryption not implemented yet');
break;
}
return PEAR::raiseError('Incorrect Password');
}
/**
* Format a password using the current encryption.
*
* @param $newPassword The plaintext password to encrypt.
*
* @return String The formated password.
*/
function encryptPassword($newPassword)
{
// Encrypt the password
switch ($this->_params['encryption']) {
case "plain":
break;
case "sha":
$newPassword = "{SHA}" . base64_encode(mHash(MHASH_SHA1, $newPassword));
break;
case "crypt-md5":
function randltr() {
$retval = ord('a');
$randnum = rand() % 64;
if ($randnum < 26) $retval = $randnum + ord('a');
if ($randnum > 25) $retval = $randnum - 26 + ord('A');
if ($randnum > 51) $retval = $randnum - 52 + ord('0');
if ($randnum == 62) $retval = ord(';');
if ($randnum == 63) $retval = ord('.');
return chr($retval);
}
$salt = '$1$' . randltr() . randltr() . randltr() . randltr();
$newPassword = crypt($newPassword,$salt);
break;
case "crypt":
// The salt is left out, generated by php
$newPassword = "{crypt}" . crypt($newPassword);
break;
case "md5-hex":
$newPassword = md5($newPassword);
break;
case "md5-base64":
$newPassword = "{MD5}" . base64_encode(mHash(MHASH_MD5,
$newPassword));
break;
case "ssha":
$salt = mhash_keygen_s2k(MHASH_SHA1,$newPassword,substr(pack("h*",md5(mt_rand())),0,8),4);
$newPassword = "{SSHA}" . base64_encode(mHash(MHASH_SHA1, $newPassword . $salt) . $salt);
break;
case "smd5":
$salt = mhash_keygen_s2k(MHASH_MD5,$newPassword,substr(pack("h*",md5(mt_rand())),0,8),4);
$newPassword = "{SMD5}" . base64_encode(mHash(MHASH_SMD5, $newPassword . $salt) . $salt);
break;
default:
return PEAR::raiseError(_("Password module is not properly configured"));
break;
}
return $newPassword;
}
/**
* Change the user's password.
*
* @param $username The user for which to change the password.
* @param $oldpassword The old (current) user password.
* @param $newpassword The new user password to set.
*
* @return boolean True or false based on success of the change.
*/
function change_password($user_name, $old_password, $new_password) {
return new PEAR_Error(_("Backend not correctly implemented."));
}
/**
* Change the Horde/IMP cached credentials. Should be called only
* after a successful change of the password in the actual backend
* storage. This routine is the same for all backends and should
* not be implemented in the backend classes.
*
* @param $username The username we're changing.
* @param $oldpassword The old user password.
* @param $newpassword The new user password to set.
*
* @return none
*/
function reset_credentials($username, $oldpassword, $newpassword) {
if (Auth::getAuth() == $username &&
Auth::getCredential('password') == $oldpassword) {
$credentials['transparent'] = Auth::getCredential('transparent');
$credentials['password'] = $newpassword;
Auth::setAuth(Auth::getAuth(), $credentials);
if (isset($_SESSION['imp']['pass']) &&
$oldpassword == $_SESSION['imp']['pass']) {
$_SESSION['imp']['pass'] = Secret::write(Secret::getKey('imp'),
$newpassword);
}
}
}
}
More information about the sork
mailing list