diff --git modules/user/user.module modules/user/user.module
index 192a67a..f9cf7e5 100644
--- modules/user/user.module
+++ modules/user/user.module
@@ -931,6 +931,7 @@ function user_account_form(&$form, &$form_state) {
     '#attributes' => array('class' => array('username')),
     '#default_value' => (!$register ? $account->name : ''),
     '#access' => ($register || ($user->uid == $account->uid && user_access('change own username')) || $admin),
+    '#weight' => -10,
   );
 
   $form['account']['mail'] = array(
@@ -950,6 +951,32 @@ function user_account_form(&$form, &$form_state) {
       '#size' => 25,
       '#description' => t('To change the current user password, enter the new password in both fields.'),
     );
+    // To skip the current password field, the user must have logged in via a
+    // one-time link and have the token in the URL.
+    $pass_reset = isset($_SESSION['pass_reset_' . $account->uid]) && isset($_GET['pass-reset-token']) && ($_GET['pass-reset-token'] == $_SESSION['pass_reset_' . $account->uid]);
+    $protected_values = array();
+    $current_pass_description = '';
+    // The user may only change their own password without their current
+    // password and only if they logged in via a one-time login link.
+    $not_my_account = ($user->uid != $account->uid);
+    if ($not_my_account || !$pass_reset) {
+      $protected_values['mail'] = $form['account']['mail']['#title'];
+      $protected_values['pass'] = t('Password');
+      $current_pass_description = t('Enter your current password to change the %mail or %pass.', array('%mail' => $protected_values['mail'], '%pass' => $protected_values['pass']));
+    }
+    $form['account']['current_pass_required_values'] = array(
+      '#type' => 'value',
+      '#value' => $protected_values,
+    );
+    $form['account']['current_pass'] = array(
+      '#type' => 'password',
+      '#title' => $not_my_account ? t('Your own current password') : t('Current password'),
+      '#size' => 25,
+      '#access' => !empty($protected_values),
+      '#description' => $current_pass_description,
+      '#weight' => -5,
+    );
+    $form['#validate'][] = 'user_validate_current_pass';
   }
   elseif (!variable_get('user_email_verification', TRUE) || $admin) {
     $form['account']['pass'] = array(
@@ -1046,6 +1073,30 @@ function user_account_form(&$form, &$form_state) {
 }
 
 /**
+ * Form validation handler for the current password on the user_account_form().
+ */
+function user_validate_current_pass(&$form, &$form_state) {
+  global $user;
+
+  $account = $form['#user'];
+  foreach ($form_state['values']['current_pass_required_values'] as $key => $name) {
+    // This validation only works for required textfields (like mail) or
+    // form values like password_confirm that have their own validation
+    // that prevent them from being empty if they are changed.
+    if ((strlen(trim($form_state['values'][$key])) > 0) && ($form_state['values'][$key] != $account->$key)) {
+      require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
+      $current_pass_failed = empty($form_state['values']['current_pass']) || !user_check_password($form_state['values']['current_pass'], $user);
+      if ($current_pass_failed) {
+        form_set_error('current_pass', t("Your current password is missing or incorrect; it's required to change the %name.", array('%name' => $name)));
+        form_set_error($key);
+      }
+      // We only need to check the password once.
+      break;
+    }
+  }
+}
+
+/**
  * Form validation handler for user_account_form().
  */
 function user_account_form_validate($form, &$form_state) {
@@ -3104,7 +3155,6 @@ function user_block_user_action(&$object, $context = array()) {
  * @ingroup forms
  * @see user_account_form()
  * @see user_account_form_validate()
- * @see user_account_form_submit()
  * @see user_register_submit()
  */
 function user_register_form($form, &$form_state) {
diff --git modules/user/user.pages.inc modules/user/user.pages.inc
index c4d89b3..76d3036 100644
--- modules/user/user.pages.inc
+++ modules/user/user.pages.inc
@@ -120,7 +120,10 @@ function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $a
           // user, which invalidates further use of the one-time login link.
           user_login_finalize();
           drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'));
-          drupal_goto('user/' . $user->uid . '/edit');
+          // Let the user's password be changed without the current password check.
+          $token = md5(drupal_random_bytes(55));
+          $_SESSION['pass_reset_' . $user->uid] = $token;
+          drupal_goto('user/' . $user->uid . '/edit', array('query' => array('pass-reset-token' => $token)));
         }
         else {
           $form['message'] = array('#markup' => t('<p>This is a one-time login for %user_name and will expire on %expiration_date.</p><p>Click on this button to log in to the site and change your password.</p>', array('%user_name' => $account->name, '%expiration_date' => format_date($timestamp + $timeout))));
@@ -219,7 +222,6 @@ function template_preprocess_user_profile_category(&$variables) {
  * @ingroup forms
  * @see user_account_form()
  * @see user_account_form_validate()
- * @see user_account_form_submit()
  * @see user_profile_form_validate()
  * @see user_profile_form_submit()
  * @see user_cancel_confirm_form_submit()
@@ -283,6 +285,10 @@ function user_profile_form_submit($form, &$form_state) {
   user_save($account, $edit, $category);
   $form_state['values']['uid'] = $account->uid;
 
+  if ($category == 'account' && !empty($edit['pass'])) {
+    // Remove the password reset tag since a new password was saved.
+    unset($_SESSION['pass_reset_'. $account->uid]);
+  }
   // Clear the page cache because pages can contain usernames and/or profile information:
   cache_clear_all();
 
diff --git modules/user/user.test modules/user/user.test
index 6a99820..db1d259 100644
--- modules/user/user.test
+++ modules/user/user.test
@@ -1352,5 +1352,30 @@ class UserEditTestCase extends DrupalWebTestCase {
     variable_set('user_pictures', 1);
     $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
     $this->assertRaw(t('The name %name is already taken.', array('%name' => $edit['name'])));
+
+    // Test that error message appears when attempting to change mail or passs
+    // without the current password.
+    $edit = array();
+    $edit['mail'] = $this->randomName() . '@new.example.com';
+    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
+    $this->assertRaw(t("Your current password is missing or incorrect; it's required to change the %name.", array('%name' => t('E-mail address'))));
+
+    $edit['current_pass'] = $user1->pass_raw;
+    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
+    $this->assertRaw(t("The changes have been saved."));
+
+    $edit = array();
+    $edit['pass[pass1]'] = $new_pass = $this->randomName();
+    $edit['pass[pass2]'] = $new_pass;
+    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
+    $this->assertRaw(t("Your current password is missing or incorrect; it's required to change the %name.", array('%name' => t('Password'))));
+
+    $edit['current_pass'] = $user1->pass_raw;
+    $this->drupalPost("user/$user1->uid/edit", $edit, t('Save'));
+    $this->assertRaw(t("The changes have been saved."));
+    // Make sure the user can log in with their new password.
+    $this->drupalLogout();
+    $user1->pass_raw = $new_pass;
+    $this->drupalLogin($user1);
   }
 }
