A start for a new change_password master plugin. This is not finished
authorkink <kink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Sun, 16 Nov 2003 14:26:51 +0000 (14:26 +0000)
committerkink <kink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Sun, 16 Nov 2003 14:26:51 +0000 (14:26 +0000)
(and should stay only in devel for now), but I'm committing it so others
can take a look and work on it too. Basic functionality is there, now
needs existing plugins added as backends, and implementing "extra" features
such as forcing SSL.

Again, this is a "rough" version, so please change/improve anything
you'd like to be changed.

git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@6163 7612ce4b-ef26-0410-bec9-ea0150e637f0

plugins/change_password/README [new file with mode: 0644]
plugins/change_password/backend/index.php [new file with mode: 0644]
plugins/change_password/backend/mysql.php [new file with mode: 0644]
plugins/change_password/backend/template.php [new file with mode: 0644]
plugins/change_password/config.php [new file with mode: 0644]
plugins/change_password/functions.php [new file with mode: 0644]
plugins/change_password/index.php [new file with mode: 0644]
plugins/change_password/options.php [new file with mode: 0644]
plugins/change_password/setup.php [new file with mode: 0644]
plugins/change_password/version [new file with mode: 0644]

diff --git a/plugins/change_password/README b/plugins/change_password/README
new file mode 100644 (file)
index 0000000..c3ea079
--- /dev/null
@@ -0,0 +1,27 @@
+Master Change Password plugin
+-----------------------------
+
+WHAT'S THIS?
+This plugin is a general framework for enabling the user to
+change his/her password. It allows for different backend
+to perform this task on different systems.
+
+STATUS
+Development
+
+CONFIGURATION
+Edit the file config.php to set the backend you want to use.
+Probably, you need to set some config vars in the backend too
+(backend/<yourbackend>.php).
+
+BACKENDS
+-
+-
+-
+
+
+AUTHORS
+
+
+
+$Id$
diff --git a/plugins/change_password/backend/index.php b/plugins/change_password/backend/index.php
new file mode 100644 (file)
index 0000000..a7a4c21
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * index.php
+ *
+ * Copyright (c) 1999-2003 The SquirrelMail Project Team
+ * Licensed under the GNU GPL. For full terms see the file COPYING.
+ *
+ * This file simply takes any attempt to view source files and sends those
+ * people to the login screen. At this point no attempt is made to see if
+ * the person is logged or not.
+ *
+ * $Id$
+ * @package plugins
+ */
+
+header("Location:../index.php");
+
+/* pretty impressive huh? */
+
+?>
diff --git a/plugins/change_password/backend/mysql.php b/plugins/change_password/backend/mysql.php
new file mode 100644 (file)
index 0000000..bb40be0
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+/* MySQL change password backend
+ * Author: Thijs Kinkhorst <kink@squirrelmail.org>
+ */
+
+/**
+ * Config vars
+ */
+
+global $mysql_server, $mysql_database, $mysql_table, $mysql_userid_field,
+       $mysql_password_field, $mysql_manager_id, $mysql_manager_pw;
+
+// The MySQL Server
+$mysql_server = 'localhost';
+$mysql_database = 'email';
+$mysql_table = 'users';
+
+// The names of the user ID and password columns
+$mysql_userid_field = 'id';
+$mysql_password_field ='password';
+
+// The user to log into MySQL with (must have rights)
+$mysql_manager_id = 'email_admin';
+$mysql_manager_pw = 'xxxxxxx';
+
+
+// NO NEED TO CHANGE ANYTHING BELOW THIS LINE
+
+global $squirrelmail_plugin_hooks;
+$squirrelmail_plugin_hooks['change_password_dochange']['mysql'] = 
+       'cpw_mysql_dochange';
+
+/**
+ * This is the function that is specific to your backend. It takes
+ * the current password (as supplied by the user) and the desired
+ * new password. It will return an array of messages. If everything
+ * was successful, the array will be empty. Else, it will contain
+ * the errormessage(s).
+ * Constants to be used for these messages:
+ * CPW_CURRENT_NOMATCH -> "Your current password is not correct."
+ * CPW_INVALID_PW -> "Your new password contains invalid characters."
+ *
+ * @param array data The username/currentpw/newpw data. 
+ * @return array Array of error messages.
+ */
+function cpw_mysql_dochange($data)
+{
+    // unfortunately, we can only pass one parameter to a hook function,
+    // so we have to pass it as an array.
+    $username = $data['username'];
+    $curpw = $data['curpw'];
+    $newpw = $data['newpw'];
+
+    $msgs = array();
+
+    global $mysql_server, $mysql_database, $mysql_table, $mysql_userid_field,
+           $mysql_password_field, $mysql_manager_id, $mysql_manager_pw;
+
+    $ds = mysql_pconnect($mysql_server, $mysql_manager_id, $mysql_manager_pw);
+    if (! $ds) {
+        array_push($msgs, _("Cannot connect to Database Server, please try later!"));
+       return $msgs;
+    }
+    if (!mysql_select_db($mysql_database, $ds)) {
+        array_push($msgs, _("Database not found on server"));
+       return $msgs;
+    }
+
+    $query_string = 'SELECT ' . $mysql_userid_field . ',' . $mysql_password_field
+                  . ' FROM '  . $mysql_table
+                  . ' WHERE ' . $mysql_userid_field . '="' . mysql_escape_string($username) .'"'
+                 . ' AND ' . $mysql_password_field . '="' . mysql_escape_string($curpw) . '"';
+    $select_result = mysql_query($query_string, $ds);
+    if (!$select_result) {
+        array_push($msgs, _("SQL call failed, try again later."));
+       return $msgs;
+    }
+
+    if (mysql_num_rows($select_result) == 0) {
+        array_push($msgs, CPW_CURRENT_NOMATCH);
+        return $msgs;
+    }
+    if (mysql_num_rows($select_result) > 1) {
+        //make sure we only have 1 uid
+        array_push($msgs, _("Duplicate login entries detected, cannot change password!"));
+        return $msgs;
+    }
+
+    $update_string = 'UPDATE '. $mysql_table . ' SET ' . $mysql_password_field
+                   . ' = "' . mysql_escape_string($cp_newpass) . '"'
+                  . ' WHERE ' . $mysql_userid_field . ' = "' . mysql_escape_string($username) . '"';
+    if (!mysql_query($update_string, $ds)) {
+        array_push($msgs, _("Password change was not successful!"));
+    }
+
+    return $msgs;
+}
diff --git a/plugins/change_password/backend/template.php b/plugins/change_password/backend/template.php
new file mode 100644 (file)
index 0000000..2669fc2
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+/*
+ This is a template for a password changing mechanism. Currently,
+ this contains two parts: the first is to register your function
+ in the squirrelmail_plugin_hooks global, and the second is
+ the function that does the actual changing.
+
+ Replace the word template everywhere with a name for your backend.
+ */
+
+/**
+ * Config vars: here's room for config vars specific to your
+ * backend.
+ */
+
+/**
+ * Define here the name of your password changing function.
+ */
+global $squirrelmail_plugin_hooks;
+$squirrelmail_plugin_hooks['change_password_dochange']['template'] = 
+       'cpw_template_dochange';
+
+/**
+ * This is the function that is specific to your backend. It takes
+ * the current password (as supplied by the user) and the desired
+ * new password. It will return an array of messages. If everything
+ * was successful, the array will be empty. Else, it will contain
+ * the errormessage(s).
+ * Constants to be used for these messages:
+ * CPW_CURRENT_NOMATCH -> "Your current password is not correct."
+ * CPW_INVALID_PW -> "Your new password contains invalid characters."
+ *
+ * @param array data The username/currentpw/newpw data. 
+ * @return array Array of error messages.
+ */
+function cpw_template_dochange($data)
+{
+    // unfortunately, we can only pass one parameter to a hook function,
+    // so we have to pass it as an array.
+    $username = $data['username'];
+    $curpw = $data['curpw'];
+    $newpw = $data['newpw'];
+
+    $msgs = array();
+
+    // your code here to change the password for $username from
+    // $currentpw into $newpw.
+    user_error('No valid backend defined: this is just a template', E_USER_ERROR);
+
+    return $msgs;
+}
diff --git a/plugins/change_password/config.php b/plugins/change_password/config.php
new file mode 100644 (file)
index 0000000..484734e
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+
+/* Change Password plugin configuration vars
+ *
+ * NOTE: probably you need to configure your specific backend too!
+ *
+ * $Id $
+ */
+
+// the password changing mechanism you're using
+$cpw_backend = 'template';
+
+
+$cpw_pass_min_length = 4;
+$cpw_pass_max_length = 25;
+
+$cpw_require_ssl = FALSE;
diff --git a/plugins/change_password/functions.php b/plugins/change_password/functions.php
new file mode 100644 (file)
index 0000000..3bd0a0f
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * Will verify the input against a set of criteria:
+ * is every field supplied, does verify password match,
+ * does current password validate, ..
+ * These criteria are for now backend-independant.
+ * @return array Array with zero or more error messages.
+ */
+function cpw_check_input()
+{
+    global $cpw_pass_min_length, $cpw_pass_max_length;
+
+    // formdata
+    sqgetGlobalVar('cpw_curpass', $currentpw, SQ_POST);
+    sqgetGlobalVar('cpw_newpass', $newpw,     SQ_POST);
+    sqgetGlobalVar('cpw_verify',  $verifypw,  SQ_POST);
+    // for decrypting current password
+    sqgetGlobalVar('key',         $key,       SQ_COOKIE);
+    sqgetGlobalVar('onetimepad',  $onetimepad,SQ_SESSION);
+
+    $msg = array();
+
+    if(!$currentpw) {
+        $msg[] = _("You must type in your current password.");
+    } elseif($currentpw != OneTimePadDecrypt($key, $onetimepad)) {
+        $msg[] = _("Your current password is not correct.");
+    }
+    if(!$newpw) {
+        $msg[] = _("You must type in a new password.");
+    }
+    if(!$verifypw) {
+        $msg[] = _("You must also type in your new password in the verify box.");
+    } elseif ($verifypw != $newpw) {
+        $msg[] = _("Your new password does not match the verify password.");
+    }
+    if($newpw && (strlen($newpw) < $cpw_pass_min_length ||
+                  strlen($newpw) > $cpw_pass_max_length ) ) {
+        $msg[] = sprintf(_("Your new password should be %s to %s characters long."),
+                 $cpw_pass_min_length, $cpw_pass_max_length);
+    }
+
+    // do we need to do checks that are backend-specific and should
+    // be handled by a hook? I know of none now, but if there's a need
+    // for it we can add a hook for that here.
+    // those checks can also be done in the backend dochange() function.
+
+    return $msg;
+}
+
+
+define('CPW_CURRENT_NOMATCH', _("Your current password is not correct."));
+define('CPW_INVALID_PW', _("Your new password contains invalid characters."));
+
+/**
+ * Does the actual password changing (meaning it calls the hook function
+ * from the backend that does this. If something goes wrong, return error
+ * message(s). If everything ok, change the password in the session so the
+ * user doesn't have to log out, and redirect back to the options screen.
+ */
+function cpw_do_change()
+{
+    global $cpw_backend;
+    sqgetGlobalVar('cpw_current', $curpw,      SQ_POST);
+    sqgetGlobalVar('cpw_new',     $newpw,      SQ_POST);
+    sqgetGlobalVar('base_uri',    $base_uri,   SQ_SESSION);
+    sqgetGlobalVar('onetimepad',  $onetimepad, SQ_SESSION);
+    sqgetGlobalVar('key',         $key,        SQ_COOKIE);
+    sqgetGlobalVar('username',    $username,   SQ_SESSION);
+
+    require_once(SM_PATH . 'plugins/change_password/backend/'.$cpw_backend.'.php');
+
+    $msgs = do_hook_function('change_password_dochange',
+        array (
+            'username' => $username,
+           'curpw' => $curpw,
+           'newpw' => $newpw
+       ) );
+
+    /* something bad happened, return */
+    if(count($msgs) > 0) {
+        return $msgs;
+    }
+
+    /* update our password stored in the session */
+    $onetimepad = OneTimePadCreate(strlen($newpw));
+    $_SESSION['onetimepad'] = $onetimepad;
+    $key = OneTimePadEncrypt($newpw, $onetimepad);
+    setcookie('key', $key, 0, $base_uri);
+
+    /* make sure we write the session data before we redirect */
+    session_write_close();
+    header('Location: '.get_location(). '/options.php?optmode=submit&plugin_change_password=1');
+    exit;
+}
diff --git a/plugins/change_password/index.php b/plugins/change_password/index.php
new file mode 100644 (file)
index 0000000..a7a4c21
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * index.php
+ *
+ * Copyright (c) 1999-2003 The SquirrelMail Project Team
+ * Licensed under the GNU GPL. For full terms see the file COPYING.
+ *
+ * This file simply takes any attempt to view source files and sends those
+ * people to the login screen. At this point no attempt is made to see if
+ * the person is logged or not.
+ *
+ * $Id$
+ * @package plugins
+ */
+
+header("Location:../index.php");
+
+/* pretty impressive huh? */
+
+?>
diff --git a/plugins/change_password/options.php b/plugins/change_password/options.php
new file mode 100644 (file)
index 0000000..3134c30
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+
+define('SM_PATH','../../');
+
+include_once (SM_PATH . 'include/validate.php');
+include_once (SM_PATH . 'functions/page_header.php');
+include_once (SM_PATH . 'plugins/change_password/functions.php');
+include_once (SM_PATH . 'plugins/change_password/config.php');
+
+/* the form was submitted, go for it */
+if(sqgetGlobalVar('cpw_go', $cpw_go, SQ_POST)) {
+    /* perform basic checks */
+    $Messages = cpw_check_input();
+    /* if no errors, go ahead with the actual change */
+    if(count($Messages) == 0) {
+        $Messages = cpw_do_change();
+    }
+}
+
+displayPageHeader($color, 'None');
+
+?>
+
+<br />
+<table align="center" cellpadding="2" cellspacing="2" border="0">
+<tr><td bgcolor="<?php echo $color[0] ?>">
+   <center><b><?php echo _("Change Password") ?></b></center>
+</td><?php
+
+if (isset($Messages) && count($Messages) > 0) {
+    echo "<tr><td>\n";
+    foreach ($Messages as $line) {
+        echo htmlspecialchars($line) . "<br />\n";
+    }
+    echo "</td></tr>\n";
+}
+
+?><tr><td>
+    <form method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
+    <table>
+      <tr>
+        <th align="right"><?php echo _("Current Password:")?></th>
+        <td><input type="password" name="cpw_curpass" value="" size="20" /></td>
+      </tr>
+      <tr>
+        <th align="right"><?php echo _("New Password:")?></th>
+        <td><input type="password" name="cpw_newpass" value="" size="20" /></td>
+      </tr>
+      <tr>
+        <th align=right><?php echo _("Verify New Password:")?></th>
+        <td><input type="password" name="cpw_verify" value="" size="20" /></td>
+      </tr>
+      <tr>
+        <td align="center" colspan="2">
+        <input type="submit" name="cpw_go" value="<?php echo _("Change Password") ?>" /></td>
+      </tr>
+    </table>
+    </form>
+</td></tr>
+</tr></table>
+</body></html>
diff --git a/plugins/change_password/setup.php b/plugins/change_password/setup.php
new file mode 100644 (file)
index 0000000..31b8bde
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * Generic Change Password plugin
+ *
+ * This plugin aims to provide a general framework for all password
+ * changing methods that currently have their own plugins.
+ *
+ * $Id $
+ */
+
+function squirrelmail_plugin_init_change_password() {
+    global $squirrelmail_plugin_hooks;
+
+    $squirrelmail_plugin_hooks['optpage_register_block']['change_password'] = 'change_password_optpage';
+}
+
+function change_password_optpage() {
+    global $optpage_blocks;
+
+    $optpage_blocks[] = array(
+        'name' => _("Change Password"),
+        'url' => '../plugins/change_password/options.php',
+        'desc' => _("Use this to change your email password."),
+        'js' => FALSE
+    );
+}
+
+function change_password_version() {
+    return '0.1';
+}
diff --git a/plugins/change_password/version b/plugins/change_password/version
new file mode 100644 (file)
index 0000000..60879d1
--- /dev/null
@@ -0,0 +1,2 @@
+Change Password
+0.1