Roundcube Community Forum

Third Party Contributions => API Based Plugins => Topic started by: Kaz on April 26, 2010, 11:11:53 AM

Title: Dovecot-SQL Driver for Password
Post by: Kaz on April 26, 2010, 11:11:53 AM
I was looking around the forums and couldn't find any solution for using other algorithms with the SQL driver, so I decided to write my own modified version of the driver so it can use any algorithm dovecot can.

I haven't tested it extensively, so it may need adjusting but so far it's 100% compatible with CRAM-MD5. The SQL query syntax is the same as the SQL driver, with the exception that in this driver %c and %n have the same value.

All in all this should be a drop in replacement for the SQL driver... Well, that killed 45 minutes, time for coffee.;D

Important note: DIGEST-MD5 will not work. Also, the query given here is meant for a database setup for use with postfixadmin. Lastly, if SELinux is enabled on your system, this script may not work without additional policies in place.


set driver in (roundcube root)/plugins/password/config.inc.php:
$rcmail_config['password_driver'] = 'dovecotpw-sql';

Add these lines to (roundcube root)/plugins/password/config.inc.php:
// dovecotpw executable, default '/usr/sbin/dovecotpw'(CentOS)
$rcmail_config['password_dovecotpw'] = '/usr/sbin/dovecotpw';

// dovecotpw algorithm, default 'CRAM-MD5', run 'dovecotpw -l' to list possibilities, DIGEST-MD5 will not work
$rcmail_config['password_dovecotpw_algorithm'] = 'CRAM-MD5';

// PEAR database DSN
$rcmail_config['password_dovecotpw_db_dsn'] = 'mysql://db_user:db_pass@unix(/var/lib/mysql/mysql.sock)/database_name';

// SQL Query see SQL Driver for details about syntax
$rcmail_config['password_dovecotpw_query'] = 'UPDATE mailbox SET password = %c, modified=now() WHERE username = %u LIMIT 1;';

Create this file (roundcube root)/plugins/password/drivers/dovecotpw-sql.php

/**
 * dovecot-SQL Password Driver
 *
 * Driver for passwords stored in SQL database encrypted using the dovecotpw utility
 *
 * @version 0.1
 * @author Kaz Walker
 * @contributing author Aleksander 'A.L.E.C' Machniak
 *
 */

function password_save($curpass, $passwd)
{
$rcmail = rcmail::get_instance();

if (!($sql = $rcmail->config->get('password_dovecotpw_query')))
  $sql = 'SELECT update_passwd(%c, %u)';

if ($dsn = $rcmail->config->get('password_dovecotpw_db_dsn')) {
// #1486067: enable new_link option
if (is_array($dsn) && empty($dsn['new_link']))
   $dsn['new_link'] = true;
else if (!is_array($dsn) && !preg_match('/\?new_link=true/', $dsn))
$dsn .= '?new_link=true';

$db = new rcube_mdb2($dsn, '', FALSE);
$db->set_debug((bool)$rcmail->config->get('sql_debug'));
$db->db_connect('w');
} else {
$db = $rcmail->get_dbh();
}

if ($err = $db->is_error())
return PASSWORD_ERROR;

if (!($pw_algo = $rcmail->config->get('password_dovecotpw_algorithm')))
$pw_algo = 'CRAM-MD5';

if (!($dovecotpw = $rcmail->config->get('password_dovecotpw')))
$dovecotpw = '/usr/sbin/dovecotpw';

// encrypt password
if (strpos($sql, '%c') !== FALSE) {
$enc_passwd = '';
$safe_passwd = escapeshellarg($passwd);
$dovotpw_com = "$dovecotpw -p $safe_passwd -s $pw_algo";

if ($pw_algo != null && $safe_passwd != null) {
$tmp_passwd = shell_exec($dovotpw_com);
$tmp_passwd = explode("}", $tmp_passwd);
$enc_passwd = trim($tmp_passwd[1]);
} else {
return PASSWORD_CRYPT_ERROR;
}

$sql = str_replace('%c',  $db->quote($enc_passwd, 'text'), $sql);
}

if (strpos($sql, '%n') !== FALSE) {
$safe_passwd = escapeshellarg($passwd);
$dovotpw_com = "$dovecotpw -p $safe_passwd -s $pw_algo";

if(strpos($sql, '%c') !== FALSE) {
// Do nothing, $enc_pass is already set correctly
} else if ($pw_algo != null && $safe_passwd != null) {
$enc_passwd = '';
$tmp_passwd = shell_exec($dovotpw_com);
$tmp_passwd = explode("}", $tmp_passwd);
$enc_passwd = trim($tmp_passwd[1]);
} else {
return PASSWORD_CRYPT_ERROR;
}

$sql = str_replace('%n',  $db->quote($enc_passwd, 'text'), $sql);
}

if (strpos($sql, '%q') !== FALSE) {
$enc_curpass = '';
$safe_curpass = escapeshellarg($curpass);
$dovotpw_com = "$dovecotpw -p $safe_curpass -s $pw_algo";

if ($pw_algo != null && $safe_curpass != null) {
$tmp_curpass = shell_exec($dovotpw_com);
$tmp_curpass = explode("}", $tmp_curpass);
$enc_curpass = trim($tmp_curpass[1]);
} else {
return PASSWORD_CRYPT_ERROR;
}

$sql = str_replace('%q',  $db->quote($enc_curpass, 'text'), $sql);
}

$user_info = explode('@', $_SESSION['username']);
if (count($user_info) >= 2) {
$sql = str_replace('%l', $db->quote($user_info[0], 'text'), $sql);
$sql = str_replace('%d', $db->quote($user_info[1], 'text'), $sql);
}

$sql = str_replace('%u', $db->quote($_SESSION['username'],'text'), $sql);
$sql = str_replace('%h', $db->quote($_SESSION['imap_host'],'text'), $sql);
$sql = str_replace('%p', $db->quote($passwd,'text'), $sql);
$sql = str_replace('%o', $db->quote($curpass,'text'), $sql);

$res = $db->query($sql);

if (!$db->is_error()) {
if (strtolower(substr(trim($query),0,6))=='select') {
   if ($result = $db->fetch_array($res))
return PASSWORD_SUCCESS;
} else {
   if ($db->affected_rows($res) == 1)
return PASSWORD_SUCCESS; // This is the good case: 1 row updated
}
}

return PASSWORD_ERROR;
}

?>
Title: Dovecot-SQL Driver for Password
Post by: VampX on May 11, 2010, 11:22:53 PM
Quote from: Kaz;27069I was looking around the forums and couldn't find any solution for using other algorithms with the SQL driver, so I decided to write my own modified version of the driver so it can use any algorithm dovecot can.

SWEET!!! Happy to have given this a try and feedback to follow.

Quote from: Kaz;27069I haven't tested it extensively, so it may need adjusting but so far it's 100% compatible with CRAM-MD5. The SQL query syntax is the same as the SQL driver, with the exception that in this driver %c and %n have the same value.

This almost worked. After running "/usr/sbin/dovecotpw -l" I found that my version of dovecot (1.2.11) was happy to support: CRYPT MD5 MD5-CRYPT SHA SHA1 SHA256 SMD5 SSHA SSHA256 PLAIN CLEARTEXT CRAM-MD5 HMAC-MD5 DIGEST-MD5 PLAIN-MD4 PLAIN-MD5 LDAP-MD5 LANMAN NTLM OTP SKEY RPA.

Of course I require MD5-CRYPT as that's how I've setup postfixadmin and dovecot so I altered the "dovecotpw_algorithm" in (roundcube root)/plugins/password/config.inc.php and the "pw_algo" variable in (roundcube root)/plugins/password/drivers/dovecotpw-sql.php to same. Works a treat. Thanks heaps for doing that. Much appreciated.
:-*
Title: Dovecot-SQL Driver for Password
Post by: Kaz on May 12, 2010, 10:19:24 PM
Quote from: VampX;27394This almost worked. After running "/usr/sbin/dovecotpw -l" I found that my version of dovecot (1.2.11) was happy to support: CRYPT MD5 MD5-CRYPT SHA SHA1 SHA256 SMD5 SSHA SSHA256 PLAIN CLEARTEXT CRAM-MD5 HMAC-MD5 DIGEST-MD5 PLAIN-MD4 PLAIN-MD5 LDAP-MD5 LANMAN NTLM OTP SKEY RPA.

Of course I require MD5-CRYPT as that's how I've setup postfixadmin and dovecot so I altered the "dovecotpw_algorithm" in (roundcube root)/plugins/password/config.inc.php and the "pw_algo" variable in (roundcube root)/plugins/password/drivers/dovecotpw-sql.php to same. Works a treat. Thanks heaps for doing that. Much appreciated.
:-*
Thanks, sadly about 2 hours after I wrote this, I realized that the 0.4 beta supports this functionality out of the box, so I switched to that on my server. But it's nice to know that this code lives on being useful somewhere else.:)

Just to let you know, modifying $pw_algo in (roundcube root)/plugins/password/drivers/dovecotpw-sql.php wasn't necessary, it only gets set to CRAM-MD5 is there's no algorithm setting in (roundcube root)/plugins/password/config.inc.php
Title: Re: Dovecot-SQL Driver for Password
Post by: gkout on December 22, 2012, 06:17:29 PM
Quote
Thanks, sadly about 2 hours after I wrote this, I realized that the 0.4 beta supports this functionality out of the box, so I switched to that on my server. But it's nice to know that this code lives on being useful somewhere else.:)

I know this is an old post, but it seems that dovecot functionality in the change password plugin is still missing. I did not understand the quoted part above. What functionality is included in beta 0.4?