I have seen this issue several time out there but no real solution.

Problem:
Any user can force another user's password to change... simply by selecting "request new password" and putting in their username. The user gets an email with the new.. but this feels like a violation to the user... and a pain.

Solution?
If someone requests a new password... Don't blindly change it... send an email that says...."Is this a real request authorized by you? Click here to confirm otherwise disregard this message"

Has anyone introduced this change already in 4.5 or even a planned release to 4.6 that could be backported?

David McIntosh
neofactor.com

Comments

moshe weitzman’s picture

noone has contributed code for this. it is desired by all, i'm sure.

neofactor’s picture

Hopefully Dries is looking into this as an imporrtant contribution to 4.6 release.
I will look at the module and try and set up a scope of work document... and take a stab at it... but if someone has already started.. please tell me.

David McIntosh
neofactor.com

moshe weitzman’s picture

you are misunderstanding how this project works. dries is not looking into this. he will only start looking when someone submits a patch for review. this feature is likely taking so long because no developer cares enough to do something about it.

neofactor’s picture

Patch request submitted: http://drupal.org/node/18719

David McIntosh
neofactor.com

killes@www.drop.org’s picture

There are probably several similar feature requests. Simply submitting them won't get the job done. Attaching a patch might. ;-)
--
If you have troubles with a particular contrib project, please consider filing a support request. Thanks. And, by the way, Drupal 4.6 will support PHP 5.

neofactor’s picture

OK... as a start I modified my user.module to prevent acount ids less than 10 to not be able to request a password reset. This way my Admin account and core content providers are safe. They should be smart enough to not "forget their password" anyways. Shame on them if they do!

Here is the Code I added around line 911:

  if ($account->uid <= 10 { 
  unset($account); 
  form_set_error('name', t('Sorry. The username %name is not allowed to be changed.', array('%name' => '<em>'. $edit['name'] .'</em>')));
  }

Just above this code:

if ($account)   { 

      $from = variable_get('site_mail', ini_get('sendmail_from'));
      $pass = user_password();

This is only a stop gap measure... I was thinking the next quick fix could be to require the Username and Email address... at present you can simply see a username in the posts and request a password reset... that would mess with people royally. At least with requiring both, it would be harder to guess the pairs.

Just a thought. Hope this helps someone.

David McIntosh

adrian’s picture

I plan on writing the code for this quite soon.

But we're looking at a 4.7 thing.
--
The future is so Bryght, I have to wear shades.

neofactor’s picture

Keep me posted please... I would love to contribute to the project.

One Note... the code above ... I changed mine to be ==1 so just the admin was excluded ... otherwise I got a red error around the default request password form... will tweak more... and see.

David McIntosh

chx’s picture

This was planned as an add on module. It's untested but it's code to begin with. Comment out the two lines that registers user/password in user_menu. You need a pwdreset table for this

CREATE TABLE `pwdreset` (
`name` VARCHAR( 255 ) NOT NULL ,
`time` INT NOT NULL ,
`random` VARCHAR( 40 ) NOT NULL 
);

function pwdreset_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array('path' => 'user/password', 'title' => t('request password change'),
      'callback' => 'pwdreset_page', 'access' => $user->uid == 0, 'type' => MENU_LOCAL_TASK);
    $items[] = array('path' => 'user/pwdchange', 'title' => t('request new password'),
      'callback' => 'pwdreset_change', 'access' => $user->uid == 0, 'type' => MENU_CALLBACK);
  }

  return $items;
}

function pwdreset_page() {
  if ($edit['name'] && !($account = user_load(array('name' => $edit['name'], 'status' => 1)))) {
    form_set_error('name', t('Sorry. The username %name is not recognized.', array('%name' => '<em>'. $edit['name'] .'</em>')));
  }
  else if ($edit['mail'] && !($account = user_load(array('mail' => $edit['mail'], 'status' => 1)))) {
    form_set_error('mail', t('Sorry. The e-mail address %email is not recognized.', array('%email' => '<em>'. $edit['mail'] .'</em>')));
  }
  $message = t('You must provide either a username or e-mail address.');
  if ($account) {
    db_query('DELETE FROM pwdreset WHERE time+%d < %d', variable_get('pwdreset_time', 216000), time());
    if (db_num_rows(db_query("SELECT 1 FROM pwdreset WHERE name='%s'", $account->name))) {
      unset($account);
      $message = t('You have a pending password change');
    }
  }
  if ($account) {
    mt_srand((double)microtime() * 1000000);
    $random = user_password(40);
    db_query("INSERT INTO pwdreset (name, time, random) VALUES ('%s', %d, '%s')", $account->name, time(), $random);
    $from = variable_get('site_mail', ini_get('sendmail_from'));
    $subject = t('Password change request for %username at %site', $account->name, variable_get('site_name', 'drupal'));
    $body = t('%username,\n\nYou have requested new password for %site. You may get your new password at %dynamic_change. ', array('%username' => $account->name, '%site' => variable_get('site_name', 'drupal'), '%dynamic_change' => url('user/pwdchange/'. $random, NULL, NULL, TRUE)));
    $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
    $mail_success = user_mail($account->mail, $subject, $body, $headers);
  }
  else {
    if ($edit) {
      drupal_set_message($message, 'error');
    }
    // Display form:
    $output = '<p>'. t('Enter your username <strong><em>or</em></strong> your e-mail address.') .'</p>';
    $output .= form_textfield(t('Username'), 'name', $edit['name'], 30, 64);
    $output .= form_textfield(t('E-mail address'), 'mail', $edit['mail'], 30, 64);
    $output .= form_submit(t('E-mail password change request'));
    print theme('page', form($output));
  }
}

function pwdreset_change($random) {
  if ($result = db_query("SELECT name FROM pwdreset WHERE random='%s'", $random)) {
    $name = db_result($result);
    db_query("DELETE FROM pwdreset WHERE random='%s'", $random);
    $_POST['edit'] = array('name' => $name);
    user_pass();
  }
  else {
    drupal_not_found();
  }
}

--
Drupal development: making the world better, one patch at a time. | A bedroom without a teddy is like a face without a smile.

neofactor’s picture

I will test it out and let you know...Thanks so much for the patch.
I was up last night working on it as well, but yours is way ahead.

David McIntosh
neofactor.com

rbrooks00’s picture

Juts noticed this and I was wondering how the testing went, this patch looks very promising indeed.

bloggator’s picture

Wouldn't it be easier (and safer) for everyone to just require the user to provide their email address instead of their username to request a new password?

It seems like that's what most of the big sites I frequent require.

Jeff
Bloggator.com
Get your blog on.

neofactor’s picture

I posted to module patch request area and there was a lot of progress...

Read about it all here: http://drupal.org/node/18719

David McIntosh
neofactor.com