+ Reply to Thread
Results 1 to 3 of 3

Thread: Dovecot-SQL Driver for Password

  1. #1
    Kaz
    Kaz is offline Roundcube Newcomer
    Join Date
    Apr 2010
    Posts
    3
    Downloads
    0
    Uploads
    0

    Thumbs up Dovecot-SQL Driver for Password

    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.

    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:
    PHP Code:
    $rcmail_config['password_driver'] = 'dovecotpw-sql'
    Add these lines to (roundcube root)/plugins/password/config.inc.php:
    PHP Code:
    // 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 Code:
    <?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 edited by Kaz; 04-26-2010 at 04:17 PM. Reason: Added note about SELinux

  2. #2
    VampX's Avatar
    VampX is offline Roundcube Newcomer
    Join Date
    May 2010
    Posts
    1
    Downloads
    0
    Uploads
    0

    Default

    Quote Originally Posted by Kaz View Post
    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 Originally Posted by Kaz View Post
    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.

  3. #3
    Kaz
    Kaz is offline Roundcube Newcomer
    Join Date
    Apr 2010
    Posts
    3
    Downloads
    0
    Uploads
    0

    Default

    Quote Originally Posted by VampX View Post
    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

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts