Author Topic: Dovecot-SQL Driver for Password  (Read 11443 times)

Offline Kaz

  • Newbie
  • *
  • Posts: 3
Dovecot-SQL Driver for Password
« 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
<?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 <alec@alec.pl>
 *
 */

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;
}

?>
« Last Edit: April 26, 2010, 11:17:09 AM by Kaz »

Offline VampX

  • Newbie
  • *
  • Posts: 1
    • http://scartissue.com.au
Dovecot-SQL Driver for Password
« Reply #1 on: May 11, 2010, 11:22:53 PM »
Quote from: Kaz;27069
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.


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

Quote from: Kaz;27069

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.


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.
:-*

Offline Kaz

  • Newbie
  • *
  • Posts: 3
Dovecot-SQL Driver for Password
« Reply #2 on: May 12, 2010, 10:19:24 PM »
Quote from: VampX;27394

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.
:-*

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

Offline gkout

  • Newbie
  • *
  • Posts: 1
Re: Dovecot-SQL Driver for Password
« Reply #3 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?