From 6bd74d8d51045923698f958fc917918411c6ca13 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Sat, 20 Jun 2009 03:28:33 -0400
Subject: [PATCH] - Password plugin: implemented drivers - removed password_sasl plugin

---
 /dev/null                               |  146 -------------
 plugins/password/config.inc.php         |   31 ++
 plugins/password/drivers/sql.php        |   66 ++++++
 plugins/password/localization/en_US.inc |    5 
 plugins/password/localization/et_EE.inc |    5 
 plugins/password/localization/hu_HU.inc |    1 
 plugins/password/localization/pl_PL.inc |    3 
 plugins/password/localization/nl_NL.inc |    5 
 plugins/password/README                 |  159 ++++++++++++++
 plugins/password/drivers/sasl.php       |   41 +++
 plugins/password/password.php           |  189 ++++++-----------
 11 files changed, 370 insertions(+), 281 deletions(-)

diff --git a/plugins/password/README b/plugins/password/README
new file mode 100644
index 0000000..ca53116
--- /dev/null
+++ b/plugins/password/README
@@ -0,0 +1,159 @@
+ -----------------------------------------------------------------------
+ Password Plugin for Roundcube
+ -----------------------------------------------------------------------
+
+ Plugin that adds a possibility to change user password using many
+ methods (drivers) via Settings/Password tab.
+
+ -----------------------------------------------------------------------
+ This program is free software; you can redistribute it and/or modify   
+ it under the terms of the GNU General Public License version 2         
+ as published by the Free Software Foundation.                          
+                                                                        
+ This program is distributed in the hope that it will be useful,        
+ but WITHOUT ANY WARRANTY; without even the implied warranty of         
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
+ GNU General Public License for more details.                           
+                                                                        
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.            
+
+ @version 1.2
+ @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl>
+ @author <see driver files for driver authors>
+ -----------------------------------------------------------------------
+
+ 1. 	Configuration
+ 2.	Drivers
+ 2.1. 	Database (sql)
+ 2.2.	Cyrus/SASL (sasl)
+ 3.	Driver API
+
+
+ 1. Configuration
+ ----------------
+
+ * See config.inc.php file.
+
+
+ 2. Drivers
+ ----------
+
+ Password plugin supports many password change mechanisms which are
+ handled by included drivers. Just pass driver name in 'password_driver' option.
+
+
+ 2.1. Database (sql)
+ -------------------
+
+ You can specify which database to connect by 'password_db_dsn' option and
+ what SQL query to execute by 'password_query'. See main.inc.php file for
+ more info.
+    
+ Example implementations of an update_passwd function:
+
+ - This is for use with LMS (http://lms.org.pl) database and postgres:
+
+	CREATE OR REPLACE FUNCTION update_passwd(hash text, account text) RETURNS integer AS $$
+	DECLARE
+    	    res integer;
+	BEGIN
+    	    UPDATE passwd SET password = hash
+	    WHERE login = split_part(account, '@', 1)
+		AND domainid = (SELECT id FROM domains WHERE name = split_part(account, '@', 2))
+	    RETURNING id INTO res;
+	    RETURN res;
+	END;
+	$$ LANGUAGE plpgsql SECURITY DEFINER;
+
+ - This is for use with a SELECT update_passwd(%o,%c,%u) query
+	Updates the password only when the old password matches the MD5 password
+	in the database
+
+	CREATE FUNCTION update_password (oldpass text, cryptpass text, user text) RETURNS text
+    	    MODIFIES SQL DATA
+	BEGIN
+	    DECLARE currentsalt varchar(20);
+	    DECLARE error text;
+	    SET error = 'incorrect current password';
+	    SELECT substring_index(substr(user.password,4),_latin1'$',1) INTO currentsalt FROM users WHERE username=user;
+	    SELECT '' INTO error FROM users WHERE username=user AND password=ENCRYPT(oldpass,currentsalt);
+	    UPDATE users SET password=cryptpass WHERE username=user AND password=ENCRYPT(oldpass,currentsalt);
+	    RETURN error;
+	END
+
+ Example SQL UPDATEs:
+ 
+ - Plain text passwords:
+    UPDATE users SET password=%p WHERE username=%u AND password=%o AND domain=%h LIMIT 1
+ 
+ - Crypt text passwords:
+    UPDATE users SET password=%c WHERE username=%u LIMIT 1
+
+ - Use a MYSQL crypt function (*nix only) with random 8 character salt
+    UPDATE users SET password=ENCRYPT(%p,concat(_utf8'$1$',right(md5(rand()),8),_utf8'$')) WHERE username=%u LIMIT 1
+ 
+ - MD5 stored passwords:
+    UPDATE users SET password=MD5(%p) WHERE username=%u AND password=MD5(%o) LIMIT 1
+
+
+ 2.2. Cyrus/SASL (sasl)
+ ----------------------
+
+ Cyrus SASL database authentication allows your Cyrus+RoundCube
+ installation to host mail users without requiring a Unix Shell account!
+
+ This driver only covers the "sasldb" case when using Cyrus SASL. Kerberos
+ and PAM authentication mechanisms will require other techniques to enable
+ user password manipulations.
+
+ Cyrus SASL includes a shell utility called "saslpasswd" for manipulating
+ user passwords in the "sasldb" database.  This plugin attempts to use
+ this utility to perform password manipulations required by your webmail
+ users without any administrative interaction. Unfortunately, this
+ scheme requires that the "saslpasswd" utility be run as the "cyrus"
+ user - kind of a security problem since we have chosen to SUID a small
+ script which will allow this to happen.
+
+ This driver is based on the Squirrelmail Change SASL Password Plugin.
+ See http://www.squirrelmail.org/plugin_view.php?id=107 for details.
+
+ Installation:
+
+ Edit the chgsaslpasswd.c and chgsaslpasswd.sh files as is documented
+ within them.
+
+ Compile the wrapper program:
+	gcc -o chgsaslpasswd chgsaslpasswd.c
+
+ Chown the chgsaslpasswd and chgsaslpasswd.sh to the cyrus user and group 
+ that your browser runs as, then chmod them to 4550.
+
+ For example, if your cyrus user is 'cyrus' and the apache server group is
+ 'nobody' (I've been told Redhat runs Apache as user 'apache'):
+
+	chown cyrus:nobody chgsaslpasswd
+	chmod 4550 chgsaslpasswd
+
+ Stephen Carr has suggested users should try to run the scripts on a test
+ account as the cyrus user eg;
+
+	su cyrus -c "./chgsaslpasswd -p test_account"
+
+ This will allow you to make sure that the script will work for your setup.
+ Should the script not work, make sure that:
+ 1) the user the script runs as has access to the saslpasswd|saslpasswd2
+   file and proper permissions
+ 2) make sure the user in the chgsaslpasswd.c file is set correctly.
+   This could save you some headaches if you are the paranoid type.
+
+
+ 3. Driver API
+ -------------
+ 
+ Driver file (<driver_name>.php) must define 'password_save' function with
+ two arguments. First - current password, second - new password. Function
+ may return PASSWORD_SUCCESS on success or PASSWORD_ERROR on any error.
+ See existing drivers in drivers/ directory for examples.
+ 
\ No newline at end of file
diff --git a/plugins/password/config.inc.php b/plugins/password/config.inc.php
new file mode 100644
index 0000000..8fa3292
--- /dev/null
+++ b/plugins/password/config.inc.php
@@ -0,0 +1,31 @@
+<?php
+
+// Password Plugin options
+// -----------------------
+// A driver to use for password change. Default: "sql".
+$rcmail_config['password_driver'] = 'sql';
+
+// Determine whether current password is required to change password.
+// Default: false.
+$rcmail_config['password_confirm_current'] = false;
+
+
+// SQL Driver options
+// ------------------
+// PEAR database DSN for performing the query. By default
+// Roundcube DB settings are used.
+$rcmail_config['password_db_dsn'] = '';
+
+// The SQL query used to change the password.
+// The query can contain the following macros that will be expanded as follows:
+//	%p is replaced with the plaintext new password
+//      %c is replaced with the crypt version of the new password, MD5 if available
+//    	   otherwise DES.
+//      %u is replaced with the username (from the session info)
+//      %o is replaced with the password before the change
+//      %h is replaced with the imap host (from the session info)
+// Escaping of macros is handled by this module.
+// Default: "SELECT update_passwd(%c, %u)" 
+$rcmail_config['password_query'] = 'SELECT update_passwd(%c, %u)';
+
+?>
diff --git a/plugins/password/drivers/sasl.php b/plugins/password/drivers/sasl.php
new file mode 100644
index 0000000..3613334
--- /dev/null
+++ b/plugins/password/drivers/sasl.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * SASL Password Driver
+ *
+ * Driver that adds functionality to change the users Cyrus/SASL password.
+ * The code is derrived from the Squirrelmail "Change SASL Password" Plugin
+ * by Galen Johnson.
+ *
+ * It only works with saslpasswd2 on the same host where RoundCube runs
+ * and requires shell access and gcc in order to compile the binary.
+ *
+ * For installation instructions please read the README file.
+ *
+ * @version 1.0
+ * @author Thomas Bruederli
+ */
+ 
+function password_save($currpass, $newpass)
+{
+    $curdir = realpath(dirname(__FILE__));
+    $username = escapeshellcmd($_SESSION['username']);
+
+    if ($fh = popen("$curdir/chgsaslpasswd -p $username", 'w')) {
+	fwrite($fh, $newpass."\n");
+        $code = pclose($fh);
+
+	if($code == 0)
+    	    return PASSWORD_SUCCESS;
+    } else 
+	raise_error(array(
+            'code' => 600,
+	    'type' => 'php',
+	    'file' = __FILE__,
+	    'message' => "Password plugin: Unable to execute $curdir/chgsaslpasswd"
+	), true, false);				    
+
+    return PASSWORD_ERROR;
+}
+
+?>
diff --git a/plugins/password/drivers/sql.php b/plugins/password/drivers/sql.php
new file mode 100644
index 0000000..3cac8d4
--- /dev/null
+++ b/plugins/password/drivers/sql.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * SQL Password Driver
+ *
+ * Driver for passwords stored in SQL database
+ *
+ * @version 1.0
+ * @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_query')))
+        $sql = 'SELECT update_passwd(%c, %u)';
+
+    if ($dsn = $rcmail->config->get('password_db_dsn')) {
+        $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 (strpos($sql, '%c') !== FALSE) {
+        $salt = '';
+        if (CRYPT_MD5) { 
+    	    $len = rand(3, CRYPT_SALT_LENGTH);
+        } else if (CRYPT_STD_DES) {
+    	    $len = 2;
+        } else {
+    	    return PASSWORD_CRYPT_ERROR;
+        }
+        for ($i = 0; $i < $len ; $i++) {
+    	    $salt .= chr(rand(ord('.'), ord('z')));
+        }
+        $sql = str_replace('%c',  $db->quote(crypt($passwd, CRYPT_MD5 ? '$1$'.$salt.'$' : $salt)), $sql);
+    }
+
+    $sql = str_replace('%u', $db->quote($_SESSION['username'],'text'), $sql);
+    $sql = str_replace('%p', $db->quote($passwd,'text'), $sql);
+    $sql = str_replace('%o', $db->quote($curpass,'text'), $sql);
+    $sql = str_replace('%h', $db->quote($_SESSION['imap_host'],'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;
+}
+
+?>
diff --git a/plugins/password/localization/en_US.inc b/plugins/password/localization/en_US.inc
index 9e25214..80bf1cc 100644
--- a/plugins/password/localization/en_US.inc
+++ b/plugins/password/localization/en_US.inc
@@ -11,8 +11,7 @@
 $messages['nocurpassword'] = 'Please input current password.';
 $messages['passwordincorrect'] = 'Current password incorrect.';
 $messages['passwordinconsistency'] = 'Passwords do not match, please try again.';
-$messages['nocryptfunction'] = 'The server is missing a function to encrypt your password - contact your system adminstrator.';
-$messages['internalerror'] = 'The server is updated more than one row in the database. This could be bad for all users. Contact your system adminstrator.';
-$messages['errorsaving'] = 'Could not save your new password to the database. Contact your system adminstrator.';
+$messages['nocryptfunction'] = 'The server is missing a function to encrypt your password. Contact your system adminstrator.';
+$messages['internalerror'] = 'Could not save new password. Contact your system adminstrator.';
 
 ?>
diff --git a/plugins/password/localization/et_EE.inc b/plugins/password/localization/et_EE.inc
index 9ddc0b3..61546e8 100644
--- a/plugins/password/localization/et_EE.inc
+++ b/plugins/password/localization/et_EE.inc
@@ -11,8 +11,7 @@
 $messages['nocurpassword'] = 'Palun sisesta vana parool.';
 $messages['passwordincorrect'] = 'Vana parool on vale.';
 $messages['passwordinconsistency'] = 'Paroolid ei kattu, palun proovi uuesti.';
-$messages['nocryptfunction'] = 'Serveris ei ole parooli krüpteerimiseks vajalikku funktsiooni - palun võta oma süsteemi administraatoriga ühendust.';
-$messages['internalerror'] = 'Server uuendas andmebaasis liiga palju ridu. See võib olla halb kõigile kasutajatele. Palun võta oma süsteemi administraatoriga ühendust.';
-$messages['errorsaving'] = 'Uue parooli andmebaasi salvestamine nurjus. Palun võta oma süsteemi administraatoriga ühendust.';
+$messages['nocryptfunction'] = 'Serveris ei ole parooli krüpteerimiseks vajalikku funktsiooni. Palun võta oma süsteemi administraatoriga ühendust.';
+$messages['internalerror'] = 'Uue parooli andmebaasi salvestamine nurjus. Palun võta oma süsteemi administraatoriga ühendust.';
 
 ?>
diff --git a/plugins/password/localization/hu_HU.inc b/plugins/password/localization/hu_HU.inc
index 8a4e5d6..9b5acb8 100644
--- a/plugins/password/localization/hu_HU.inc
+++ b/plugins/password/localization/hu_HU.inc
@@ -13,6 +13,5 @@
 $messages['passwordinconsistency'] = 'A két új jelszó nem egyezik.';
 $messages['nocryptfunction'] = 'Hiba történt a kérés feldolgozása során.';
 $messages['internalerror'] = 'Hiba történt a kérés feldolgozása során.';
-$messages['errorsaving'] = 'Hiba történt a kérés feldolgozása során.';
 
 ?>
diff --git a/plugins/password/localization/nl_NL.inc b/plugins/password/localization/nl_NL.inc
index 61d4e36..c289ee3 100644
--- a/plugins/password/localization/nl_NL.inc
+++ b/plugins/password/localization/nl_NL.inc
@@ -11,8 +11,7 @@
 $messages['nocurpassword'] = 'vul het huidige wachtwoord in.';
 $messages['passwordincorrect'] = 'Huidig wachtwoord is onjuist.';
 $messages['passwordinconsistency'] = 'Wachtwoorden komen niet overeen, probeer het opnieuw.';
-$messages['nocryptfunction'] = 'De server mist een functie om uw wachtwoord et beveiligen - neem contact op met uw systeembeheerder.';
-$messages['internalerror'] = 'De server heeft meer dan 1 regel in de database gewijzigd. Dit kan een probleem opleveren voor alle gebruikers. Neem contact op met uw systeembeheerder.';
-$messages['errorsaving'] = 'Uw wachtwoord kan niet worden opgeslagen in de database. Neem contact op met uw systeembeheerder.';
+$messages['nocryptfunction'] = 'De server mist een functie om uw wachtwoord et beveiligen. Neem contact op met uw systeembeheerder.';
+$messages['internalerror'] = 'Uw wachtwoord kan niet worden opgeslagen. Neem contact op met uw systeembeheerder.';
 
 ?>
diff --git a/plugins/password/localization/pl_PL.inc b/plugins/password/localization/pl_PL.inc
index 3c4acb3..e26770b 100644
--- a/plugins/password/localization/pl_PL.inc
+++ b/plugins/password/localization/pl_PL.inc
@@ -12,7 +12,6 @@
 $messages['passwordincorrect'] = 'Błędne aktualne hasło, spróbuj ponownie.';
 $messages['passwordinconsistency'] = 'Hasła nie pasują, spróbuj ponownie.';
 $messages['nocryptfunction'] = 'Brak funkcji kodującej hasło. Skontaktuj się z administratorem.';
-$messages['internalerror'] = 'Serwer zaktualizował więcej niż jeden wpis w bazie. To może być złe dla innych użytkowników. Skontaktuj się z administratorem.';
-$messages['errorsaving'] = 'Nie udało się zapisać nowego hasła. Skontaktuj się z administratorem.';
+$messages['internalerror'] = 'Nie udało się zapisać nowego hasła. Skontaktuj się z administratorem.';
 
 ?>
diff --git a/plugins/password/password.php b/plugins/password/password.php
index 767ddab..0500539 100644
--- a/plugins/password/password.php
+++ b/plugins/password/password.php
@@ -1,84 +1,37 @@
 <?php
 
-/**
- * Change Password
- *
- * Plugin that adds a possibility to change password using a database
- * (Settings -> Password tab)
- *
- * @version 1.1
- * @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl>
- * @editor Daniel Black
- *
- * Configuration Items (config/main.inc.php):
- *   password_confirm_current - boolean to determine whether current password
- *     is required to change password. Defaults to FALSE.
- *   password_db_dsn - is the PEAR database DSN for performing the query. Defaults
- *     to the default databse setting in config/db.inc.php
- *   password_query - the SQL query used to change the password.
- *     If the SQL query is a SELECT it will return an error message in a row if unsuccessful
- *     If the SQL query is a UPDATE it will update a single row only. 
- *     An UPDATE where zero rows changed will be inteperated to be a wrong username/password
- *     More than one row changed will be inteperated as an internal error
- *     The query can contain the following macros that will be expanded as follows:
- *       %p is replaced with the plaintext new password
- *       %c is replaced with the crypt version of the new password, MD5 if available
- *         otherwise DES.
- *       %u is replaced with the username (from the session info)
- *       %o is replaced with the password before the change
- *       %h is replaced with the imap host (from the session info)
- *     Escaping of macros is handled by this module.
- *     Defaults to "SELECT update_passwd(%c, %u)" 
- *     To use this you need to define the update_passwd function in your
- *     database.
- *
- * Example SQL queries:
- * These will typically need to define a function to change the password:
- * 
- * Example implementations of an update_passwd function:
- *
- * This is for use with LMS (http://lms.org.pl) database and postgres:
- * CREATE OR REPLACE FUNCTION update_passwd(hash text, account text) RETURNS integer AS $$
- * DECLARE
- *         res integer;
- * BEGIN
- *      UPDATE passwd SET password = hash
- *	WHERE login = split_part(account, '@', 1)
- *		AND domainid = (SELECT id FROM domains WHERE name = split_part(account, '@', 2))
- *	RETURNING id INTO res;
- *	RETURN res;
- * END;
- * $$ LANGUAGE plpgsql SECURITY DEFINER;
- *
- * This is for use with a SELECT update_passwd(%o,%c,%u) query
- * Uupdates the password only when the old password matches the MD5 password in the database
- * CREATE FUNCTION update_password (oldpass text, cryptpass text, user text) RETURNS text
- *        MODIFIES SQL DATA
- * BEGIN
- *   DECLARE currentsalt varchar(20);
- *   DECLARE error text;
- *   SET error = 'incorrect current password';
- *   SELECT substring_index(substr(user.password,4),_latin1'$',1) INTO currentsalt FROM users WHERE username=user;
- *   SELECT '' INTO error FROM users WHERE username=user AND password=ENCRYPT(oldpass,currentsalt);
- *   UPDATE users SET password=cryptpass WHERE username=user AND password=ENCRYPT(oldpass,currentsalt);
- *   RETURN error;
- * END
- *
- * Example SQL UPDATEs:
- * 
- *   Plain text passwords:
- *   UPDATE users SET password=%p WHERE username=%u AND password=%o AND domain=%h LIMIT 1
- * 
- *   Crypt text passwords:
- *   UPDATE users SET password=%c WHERE username=%u LIMIT 1
- *
- *   Use a MYSQL crypt function (*nix only) with random 8 character salt
- *   UPDATE users SET password=ENCRYPT(%p,concat(_utf8'$1$',right(md5(rand()),8),_utf8'$')) WHERE username=%u LIMIT 1
- * 
- *   MD5 stored passwords:
- *   UPDATE users SET password=MD5(%p) WHERE username=%u AND password=MD5(%o) LIMIT 1
- * 
- */
+/*
+ +-------------------------------------------------------------------------+
+ | Password Plugin for Roundcube                                           |
+ | Version 1.2                                                             |
+ |                                                                         |
+ | Copyright (C) 2009, RoundCube Dev. - Switzerland                        |
+ |                                                                         |
+ | This program is free software; you can redistribute it and/or modify    |
+ | it under the terms of the GNU General Public License version 2          |
+ | as published by the Free Software Foundation.                           |
+ |                                                                         |
+ | This program is distributed in the hope that it will be useful,         |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of          |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           |
+ | GNU General Public License for more details.                            |
+ |                                                                         |
+ | You should have received a copy of the GNU General Public License along |
+ | with this program; if not, write to the Free Software Foundation, Inc., |
+ | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.             |
+ |                                                                         |
+ +-------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <alec@alec.pl>                              |
+ +-------------------------------------------------------------------------+
+
+ $Id: index.php 2645 2009-06-15 07:01:36Z alec $
+
+*/
+
+define('PASSWORD_CRYPT_ERROR', 1);
+define('PASSWORD_ERROR', 2);
+define('PASSWORD_SUCCESS', 0);
+
 class password extends rcube_plugin
 {
   public $task = 'settings';
@@ -106,6 +59,7 @@
   function password_save()
   {
     $rcmail = rcmail::get_instance();
+    $this->load_config();
 
     $this->add_texts('localization/');
     $this->register_handler('plugin.body', array($this, 'password_form'));
@@ -135,8 +89,8 @@
   function password_form()
   {
     $rcmail = rcmail::get_instance();
+    $this->load_config();
 
-    $confirm = $rcmail->config->get('password_confirm_current');
     // add some labels to client
     $rcmail->output->add_label(
 	'password.nopassword',
@@ -152,7 +106,7 @@
     // return the complete edit form as table
     $out = '<table' . $attrib_str . ">\n\n";
 
-    if ($confirm) {
+    if ($rcmail->config->get('password_confirm_current')) {
       // show current password selection
       $field_id = 'curpasswd';
       $input_newpasswd = new html_passwordfield(array('name' => '_curpasswd', 'id' => $field_id,
@@ -205,55 +159,44 @@
 	), $out);
   }
 
-  private function _save($curpass,$passwd)
+  private function _save($curpass, $passwd)
   {
-    $cfg = rcmail::get_instance()->config;
-
-    if (!($sql = $cfg->get('password_query')))
-      $sql = "SELECT update_passwd(%c, %u)";
-
-    if ($dsn = $cfg->get('password_db_dsn')) {
-      $db = new rcube_mdb2($dsn, '', FALSE);
-      $db->set_debug((bool)$cfg->get('sql_debug'));
-      $db->db_connect('w');
-    } else {
-      $db = rcmail::get_instance()->get_dbh();
-    }
-
-    if ($err = $db->is_error())
-      return $err;
+    $config = rcmail::get_instance()->config;
+    $driver = $this->home.'/drivers/'.$config->get('password_driver', 'sql').'.php';
     
-    if (strpos($sql,'%c') !== FALSE) {
-      $salt = '';
-      if (CRYPT_MD5) { 
-        $len = rand(3,CRYPT_SALT_LENGTH);
-      } else if (CRYPT_STD_DES) {
-        $len = 2;
-      } else {
-        return $this->gettext('nocryptfunction');
-      }
-      for ($i = 0; $i < $len ; $i++) {
-        $salt .= chr(rand(ord('.'),ord('z')));
-      }
-      $sql = str_replace('%c',  $db->quote(crypt($passwd, CRYPT_MD5 ? '$1$'.$salt.'$' : $salt)), $sql);
+    if (!is_readable($driver)) {
+      raise_error(array(
+        'code' => 600,
+	'type' => 'php',
+	'file' => __FILE__,
+	'message' => "Password plugin: Unable to open driver file $driver"
+	), true, false);
+      return $this->gettext('internalerror');
     }
-    $sql = str_replace('%u', $db->quote($_SESSION['username'],'text'), $sql);
-    $sql = str_replace('%p', $db->quote($passwd,'text'), $sql);
-    $sql = str_replace('%o', $db->quote($curpass,'text'), $sql);
-    $sql = str_replace('%h', $db->quote($_SESSION['imap_host'],'text'), $sql);
+    
+    include($driver);
 
-    $res = $db->query($sql);
-    if ($err = $db->is_error())
-      return $err;
-    if (strtolower(substr(trim($query),0,6))=='select') {
-      return $db->fetch_array($res);
-    } else { 
-      $res = $db->affected_rows($res);
-      if ($res == 0) return $this->gettext('errorsaving');
-      if ($res == 1) return FALSE; // THis is the good case - 1 row updated
+    if (!function_exists('password_save')) {
+      raise_error(array(
+        'code' => 600,
+	'type' => 'php',
+	'file' => __FILE__,
+	'message' => "Password plugin: Broken driver: $driver"
+	), true, false);
       return $this->gettext('internalerror');
     }
 
+    $result = password_save($curpass, $passwd);
+
+    switch ($result) {
+      case PASSWORD_SUCCESS:
+        return;
+      case PASSWORD_CRYPT_ERROR;
+        return $this->gettext('nocryptfunction');
+      case PASSWORD_ERROR:
+      default:
+        return $this->gettext('internalerror');
+    }
   }
 
 }
diff --git a/plugins/sasl_password/README b/plugins/sasl_password/README
deleted file mode 100644
index 3fbc448..0000000
--- a/plugins/sasl_password/README
+++ /dev/null
@@ -1,65 +0,0 @@
-+-------------------------------------------------------------------------+
-|
-|  Author:  Thomas Bruederli
-|  Source:  Squirrelmail Change SASL Password Plugin by Galen Johnson
-|  Program: sasl_password
-|  Version: 1.0
-|  Purpose: Change Cyrus Account Passwords
-|
-+-------------------------------------------------------------------------+
-
-
-Purpose
--------
-Cyrus SASL database authentication allows your Cyrus+RoundCube
-installation to host mail users without requiring a Unix Shell account!
-
-This plugin only covers the "sasldb" case when using Cyrus SASL. Kerberos
-and PAM authentication mechanisms will require other techniques to enable
-user password manipulations.
-
-Cyrus SASL includes a shell utility called "saslpasswd" for manipulating
-user passwords in the "sasldb" database.  This patch attempts to use
-this utility to perform password manipulations required by your webmail
-users without any administrative interaction. Unfortunately, this
-scheme requires that the "saslpasswd" utility be run as the "cyrus"
-user - kind of a security problem since we have chosen to SUID a small
-script which will allow this to happen.
-
-This plugin is based on the Squirrelmail Change SASL Password Plugin.
-See http://www.squirrelmail.org/plugin_view.php?id=107 for details.
-
-
-Installation
-------------
-Install just like any other plugin, just put it in the plugin directory
-and activate it by adding 'sasl_password' to the list of active plugins
-in config/main.inc.php
-
-Edit the chgsaslpasswd.c and chgsaslpasswd.sh files as is documented
-within them.
-
-Compile the wrapper program:
-	gcc -o chgsaslpasswd chgsaslpasswd.c
-
-Chown the chgsaslpasswd and chgsaslpasswd.sh to the cyrus user and group 
-that your browser runs as, then chmod them to 4550.
-
-For example, if your cyrus user is 'cyrus' and the apache server group is
-'nobody' (I've been told Redhat runs Apache as user 'apache'):
-
-	chown cyrus:nobody chgsaslpasswd
-	chmod 4550 chgsaslpasswd
-
-Stephen Carr has suggested users should try to run the scripts on a test
-account as the cyrus user eg;
-
-	su cyrus -c "./chgsaslpasswd -p test_account"
-
-This will allow you to make sure that the script will work for your setup.
-Should the script not work, make sure that:
-1) the user the script runs as has access to the saslpasswd|saslpasswd2
-   file and proper permissions
-2) make sure the user in the chgsaslpasswd.c file is set correctly.
-   This could save you some headaches if you are the paranoid type.
-
diff --git a/plugins/sasl_password/chgsaslpasswd.c b/plugins/sasl_password/chgsaslpasswd.c
deleted file mode 100644
index 17e20c6..0000000
--- a/plugins/sasl_password/chgsaslpasswd.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-
-// set the UID this script will run as (cyrus user)
-#define UID 96
-// set the path to saslpasswd or saslpasswd2
-#define CMD "/usr/sbin/saslpasswd2"
-
-/* INSTALLING:
-  gcc -o chgsaslpasswd chgsaslpasswd.c
-  chown root.apache chgsaslpasswd
-  strip chgsaslpasswd
-  chmod 4550 chgsaslpasswd
-*/
-
-main(int argc, char *argv[])
-{
-  int rc,cc;
-
-  cc = setuid(UID);
-  rc = execvp(CMD, argv);
-  if ((rc != 0) || (cc != 0))
-  {
-    fprintf(stderr,"__ %s:  failed %d  %d\n",argv[0],rc,cc);
-    exit(1);
-  }
-}
diff --git a/plugins/sasl_password/locale/de_CH.inc b/plugins/sasl_password/locale/de_CH.inc
deleted file mode 100644
index 399efda..0000000
--- a/plugins/sasl_password/locale/de_CH.inc
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-$labels = array();
-$labels['changepasswd']  = 'Passwort ändern';
-$labels['curpasswd']  = 'Aktuelles Passwort';
-$labels['newpasswd']  = 'Neues Passwort';
-$labels['confpasswd']  = 'Passwort Wiederholung';
-
-$messages = array();
-$messages['nopassword'] = "Bitte geben Sie ein neues Passwort ein";
-$messages['nocurpassword'] = "Bitte geben Sie Ihr aktuelles Passwort an";
-$messages['passwordincorrect'] = "Das aktuelle Passwort ist nicht korrekt";
-$messages['passwordinconsistency'] = "Das neue Passwort und dessen Wiederholung stimmen nicht überein";
-$messages['successfullysaved'] = "Ihr Passwort wurde erfolgreich geändert";
-
-?>
\ No newline at end of file
diff --git a/plugins/sasl_password/locale/en_US.inc b/plugins/sasl_password/locale/en_US.inc
deleted file mode 100644
index 42708b3..0000000
--- a/plugins/sasl_password/locale/en_US.inc
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-$labels = array();
-$labels['changepasswd']  = 'Change Password';
-$labels['curpasswd']  = 'Current Password:';
-$labels['newpasswd']  = 'New Password:';
-$labels['confpasswd']  = 'Confirm New Password:';
-
-$messages = array();
-$messages['nopassword'] = "Please enter the new password";
-$messages['nocurpassword'] = "Please enter your current password";
-$messages['passwordincorrect'] = "Current password is incorrect";
-$messages['passwordinconsistency'] = "The new password and it's confirmation do not match";
-$messages['successfullysaved'] = "Successfully changed password";
-
-?>
\ No newline at end of file
diff --git a/plugins/sasl_password/locale/pl_PL.inc b/plugins/sasl_password/locale/pl_PL.inc
deleted file mode 100644
index 10cf51a..0000000
--- a/plugins/sasl_password/locale/pl_PL.inc
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-$labels = array();
-$labels['changepasswd']  = 'Zmiana hasła';
-$labels['curpasswd']  = 'Aktualne hasło:';
-$labels['newpasswd']  = 'Nowe hasło:';
-$labels['confpasswd']  = 'Potwierdź hasło:';
-
-$messages = array();
-$messages['nopassword'] = "Wprowadź nowe hasło";
-$messages['nocurpassword'] = "Wprowadź aktualne hasło";
-$messages['passwordincorrect'] = 'Błędne aktualne hasło, spróbuj ponownie.';
-$messages['passwordinconsistency'] = 'Hasła nie pasują, spróbuj ponownie.';
-$messages['successfullysaved'] = "Zapisano.";
-
-?>
\ No newline at end of file
diff --git a/plugins/sasl_password/sasl_password.js b/plugins/sasl_password/sasl_password.js
deleted file mode 100644
index 719dc82..0000000
--- a/plugins/sasl_password/sasl_password.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SASL pssword change interface (tab) */
-
-function sasl_password_save()
-{
-  var input_curpasswd = $('#saslcurpasswd')[0];
-  var input_newpasswd = $('#saslnewpasswd')[0];
-  var input_confpasswd = $('#saslconfpasswd')[0];
-
-  if (input_curpasswd && input_curpasswd.value=='') {
-    alert(rcmail.gettext('nocurpassword', 'sasl_password'));
-    input_curpasswd.focus();
-  }
-  else if (input_newpasswd && input_newpasswd.value=='') {
-    alert(rcmail.gettext('nopassword', 'sasl_password'));
-    input_newpasswd.focus();
-  }
-  else if (input_confpasswd && input_confpasswd.value=='') {
-    alert(rcmail.gettext('nopassword', 'sasl_password'));
-    input_confpasswd.focus();
-  }
-  else if ((input_newpasswd && input_confpasswd) && (input_newpasswd.value != input_confpasswd.value)) {
-    alert(rcmail.gettext('passwordinconsistency', 'sasl_password'));
-    input_newpasswd.focus();
-  }
-  else {
-    rcmail.gui_objects.passform.submit();
-  }
-}
-
-if (window.rcmail) {
-  rcmail.addEventListener('init', function(evt) {
-  // <span id="settingstabdefault" class="tablink"><roundcube:button command="preferences" type="link" label="preferences" title="editpreferences" /></span>
-  var tab = $('<span>').attr('id', 'settingstabpluginsaslpassword').addClass('tablink');
-    
-  var button = $('<a>').attr('href', rcmail.env.comm_path+'&_action=plugin.saslpassword').html(rcmail.gettext('password')).appendTo(tab);
-  button.bind('click', function(e){ return rcmail.command('plugin.saslpassword', this) });
-
-  // add button and register commands
-  rcmail.add_element(tab, 'tabs');
-  rcmail.register_command('plugin.saslpassword', function() { rcmail.goto_url('plugin.saslpassword') }, true);
-  rcmail.register_command('plugin.saslpassword-save', sasl_password_save, true);
-  });
-}
diff --git a/plugins/sasl_password/sasl_password.php b/plugins/sasl_password/sasl_password.php
deleted file mode 100644
index 0152ec2..0000000
--- a/plugins/sasl_password/sasl_password.php
+++ /dev/null
@@ -1,146 +0,0 @@
-<?php
-
-/**
- * Change SASL Password
- *
- * Plugin that adds functionality ty to change the users Cyrus/SASL password.
- * The code is derrived from the Squirrelmail "Change SASL Password" Plugin
- * by Galen Johnson.
- *
- * It only works with saslpasswd2 on the same host where RoundCube runs
- * and requires shell access and gcc in order to compile the binary.
- *
- * For installation instructions please read the README file.
- *
- * @version 1.0
- * @author Thomas Bruederli
- */
-class sasl_password extends rcube_plugin
-{
-  public $task = 'settings';
-
-  function init()
-  {
-    $rcmail = rcmail::get_instance();
-    // add Tab label
-    $rcmail->output->add_label('password');
-    $this->register_action('plugin.saslpassword', array($this, 'password_init'));
-    $this->register_action('plugin.saslpassword-save', array($this, 'password_save'));
-    $this->include_script('sasl_password.js');
-  }
-
-  function password_init()
-  {
-    $this->add_texts('locale/');
-    $this->register_handler('plugin.body', array($this, 'password_form'));
-
-    $rcmail = rcmail::get_instance();
-    $rcmail->output->set_pagetitle($this->gettext('changepasswd'));
-    $rcmail->output->send('plugin');
-  }
-  
-  function password_save()
-  {
-    $rcmail = rcmail::get_instance();
-
-    $this->add_texts('locale/');
-    $this->register_handler('plugin.body', array($this, 'password_form'));
-
-    if (!isset($_POST['_curpasswd']) || !isset($_POST['_newpasswd'])) {
-      $rcmail->output->command('display_message', $this->gettext('nopassword'), 'error');
-    }
-    else {
-      $curpwd = get_input_value('_curpasswd', RCUBE_INPUT_POST);
-      $newpwd = get_input_value('_newpasswd', RCUBE_INPUT_POST);
-
-      if ($rcmail->decrypt($_SESSION['password']) != $curpwd) {
-        $rcmail->output->command('display_message', $this->gettext('passwordincorrect'), 'error');
-      }
-      else if ($this->_save($newpwd)) {
-        $rcmail->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation');
-        $_SESSION['password'] = $rcmail->encrypt($newpwd);
-      }
-      else {
-        $rcmail->output->command('display_message', $this->gettext('errorsaving'), 'error');
-      }
-    }
-
-    rcmail_overwrite_action('plugin.saslpassword');
-    rcmail::get_instance()->output->send('plugin');
-  }
-
-  function password_form()
-  {
-    $rcmail = rcmail::get_instance();
-
-    // add some labels to client
-    $rcmail->output->add_label(
-        'sasl_password.nopassword',
-        'sasl_password.nocurpassword',
-        'sasl_password.passwordinconsistency',
-        'sasl_password.changepasswd'
-    );
-
-    $table = new html_table(array('cols' => 2));
-
-    // show current password selection
-    $field_id = 'saslcurpasswd';
-    $input_newpasswd = new html_passwordfield(array('name' => '_curpasswd', 'id' => $field_id, 'size' => 25));
-
-    $table->add('title', html::label($field_id, Q($this->gettext('curpasswd'))));
-    $table->add(null, $input_newpasswd->show());
-
-    // show new password selection
-    $field_id = 'saslnewpasswd';
-    $input_newpasswd = new html_passwordfield(array('name' => '_newpasswd', 'id' => $field_id, 'size' => 25));
-
-    $table->add('title', html::label($field_id, Q($this->gettext('newpasswd'))));
-    $table->add(null, $input_newpasswd->show());
-
-    // show confirm password selection
-    $field_id = 'saslconfpasswd';
-    $input_confpasswd = new html_passwordfield(array('name' => '_confpasswd', 'id' => $field_id, 'size' => 25));
-
-    $table->add('title', html::label($field_id, Q($this->gettext('confpasswd'))));
-    $table->add(null, $input_confpasswd->show());
-
-    $out = html::div(array('class' => "settingsbox", 'style' => "margin:0"),
-      html::div(array('id' => "userprefs-title"), $this->gettext('changepasswd')) .
-      html::div(array('style' => "padding:15px"), $table->show() .
-        html::p(null,
-          $rcmail->output->button(array(
-            'command' => 'plugin.saslpassword-save',
-            'type' => 'input',
-            'class' => 'button mainaction',
-            'label' => 'save'
-        )))
-      )
-    );
-
-    $rcmail->output->add_gui_object('passform', 'password-form');
-
-    return $rcmail->output->form_tag(array(
-        'id' => 'password-form',
-        'name' => 'password-form',
-        'method' => 'post',
-        'action' => './?_task=settings&_action=plugin.saslpassword-save',
-    ), $out);
-  }
-
-  private function _save($passwd)
-  {
-    $curdir = realpath(dirname(__FILE__));
-    $username = escapeshellcmd($_SESSION['username']);
-    $code = 1;
-
-    if ($fh = popen("$curdir/chgsaslpasswd -p $username", 'w')) {
-      fwrite($fh, $passwd."\n");
-      $code = pclose($fh);
-    }
-
-    return ($code == 0);
-  }
-
-}
-
-?>

--
Gitblit v1.9.1