SID-02006: ResetPassword / ChangePassword causing problem
| Status: |
Answered |
TWiki version: |
5.1.2 |
Perl version: |
5.10.1 |
| Category: |
CategoryAuthentication |
Server OS: |
RHEL 6 x86_64 |
Last update: |
7 years ago |
When a user is executing
ResetPassword the mcp (
MustChangePassword) is being set in .htpasswd (which is expected) and user receives email with temporary password.
When user then goes to the Change Password form as provided in the link attached to the mail he then enters old password (the temporary one provided in the email) and selects a new password and clicks "Change Password"
This causes the
ChangePassword form to be loaded again (this time with username and mcp value added to URL: /bin/view/TWiki/ChangePassword?username=StenJorgensen;mcp=1
No matter how many times this procedure is repeated the result is the same - mcp is set to 1 (can be confirmed in .htpasswd file), and this causes the
ChangePassword form to load again (which is expected as long as mcp is 1)
Seems like mcp somehow should have been reset to 0, but this never happens.
The workaround for this is to manually change mcp to 0 in the .htpasswd file for the user in question and then ask him to do as he is told in the email.
As I see it this is erroneous behaviour by TWiki (not resetting mcp when password has been changed).
Can it be confirmed whether this is corrected in later TWiki versions or if it will be corrected in the future?
--
Sten Storgaard - 2014-12-23
Discussion and Answer
This looks like a bug. I wonder if this is browser specific. Could you try a different browser?
--
Peter Thoeny - 2014-12-23
Possibly related to
TWikibug:Item7584
: Template login not working with IIS 7.5 on Windows and Safari on iOS.
--
Peter Thoeny - 2014-12-23
Back from Xmas vacation..
I just tried the operation on Firefox from a Linux machine and the same issue occured.
I looked at Item 7584 and I can see that they might be related, but I haven't found in the code where the MCP is being read (and written), so I can't tell if there might be a (faulty?) use of defined()
--
Sten Storgaard - 2015-01-02
Check this:
-
sub checkAccess in lib/TWiki/UI.pm
-
sub getMustChangePassword in lib/TWiki/Users/HtPasswdUser.pm assuming you use TWiki::Users::HtPasswdUser for {PasswordManager}
--
Peter Thoeny - 2015-01-02
First things first: We are indeed using
HtPasswdUser:
$TWiki::cfg{PasswordManager} = 'TWiki::Users::HtPasswdUser';
And we also have this (default I assume) setting in TWiki.spec:
$TWiki::cfg{MustChangePasswordAfterReset} = $TRUE;
So far so good..
checkAccess says this:
if( $session->{users}->getMustChangePassword( $user )
&& "$web.$topic" ne "$TWiki::cfg{SystemWebName}.ChangePassword"
) {
my $wikiname = $session->{users}->getWikiName( $user ) || $user;
my $url = $session->getScriptUrl( 1, 'view',
$TWiki::cfg{SystemWebName}, 'ChangePassword',
username => $wikiname,
mcp => '1' );
$session->redirect( $url );
}
}
I am no expert here, but as far as I can see it checks whether mcp is set and called page is anything but "ChangePassword" - if this is the case then
ChangePassword is called with mcp = 1 - this looks fine as well..
As far as I can follow the code changePassword is defined in TWiki/UI/Register.pm and after some sanity checks it calls setPassword:
unless( $users->setPassword( $cUID, $passwordA, $oldpassword )) {
And since we are using TWiki::Users::HtPasswdUser for {PasswordManager} this is defined in Users/HtPasswdUser.pm - in here I see this:
sub setPassword {
my ( $this, $login, $newUserPassword, $oldUserPassword, $mcp ) =
@_
;
if ( defined( $oldUserPassword ) ) {
unless ( $oldUserPassword eq '1' ) {
return 0 unless $this->checkPassword( $login, $oldUserPassword );
}
} elsif ( $this->fetchPass( $login ) ) {
$this->{error} = $login . ' already exists';
return 0;
}
my $db = $this->_readPasswd();
unless( $this->{error} ) {
$db->{$login}->{pass} = $this->encrypt( $login, $newUserPassword, 1 );
$db->{$login}->{emails} ||= '';
$db->{$login}->{pwdChgTime} = time();
$db->{$login}->{mustChgPwd} = $mcp ? 1 : 0;
$this->_savePasswd( $db );
}
if( $this->{error} ) {
print STDERR "ERROR: failed to resetPassword - " . $this->{error};
return undef;
}
$this->{error} = undef;
return 1;
}
As I said I am not a perl expert whatsoever, but what comes to my mind is this line:
$db->{$login}->{mustChgPwd} = $mcp ? 1 : 0;
I am not 100% sure where $mcp comes from and what the value is by the time setPassword is called, but it would make sense to me if it is TRUE.
As I see it the above line is executed if _readPasswd() returns without error, after which the new password is encrypted and set and time of password change is updated.
Now the line above - correct me if I am wrong, but according to my (limited) perl skills this is a simple condition check - if $mcp is TRUE then value {mustChgPwd} is set to 1 - otherwise 0 - correct?
If I am correct then it seems strange to me that the above setting is not the opposite way - setting {mustChgPwd) to 0 when password is successfully set.
A simple check could be to reverse the order of 1 and 0 in the line above and check, but I am not sure about the side-effects here. If setPassword is also used to set the temporary password when user requests the password reset, then it of course makes no sense to set the value to 0 (at least not until user has set a new password)
--
Sten Storgaard - 2015-01-02
Users/HtPasswdUser.pm has
setPassword with
$mcp as the 4th parameter. On a password reset this is set if the
{MustChangePasswordAfterReset} configure setting is set (which it is by default).
On change password the 4th parameter is missing, e.g. has value undefined, which equals to 0 on a test. So the code looks correct to me.
I recommend to add some debug statements in
setPassword of
Users/HtPasswdUser.pm, such as:
print STDERR "in setPassword: mcp is $mcp\n";
See debug output in the Apache error log.
--
Peter Thoeny - 2015-01-03
I have now tried to add some debug messages in some places I consider interesting, and then I went through a cycle of Password reset, login using the temporary credentials from the email and three (failing) attempts to change the password - followed by a manual change of mcp in the .htpasswd file and a successful password change attempt..
I have attached two files to this support item: the wiki-error log and the wiki-access log - found it better than listing it all here..
Two things jumps to my mind when reading the logs:
1: setPassword is never called until I have changed mcp manually
2: I get authentication failure for every password change attempt - even for the successful attempt. The same temporary password from email is used in every attempt and I see no indication on the screen that authentication fails - it is only saying that password change is required on the failing attempts
--
Sten Storgaard - 2015-01-07
Oops - sorry about the triple comment above.
Had some problems accessing twiki.org and couldn't see the comment so I reposted a couple of times..
--
Sten Storgaard - 2015-01-07
NP. Today we had a greedy spider that slowed down TWiki for all of us, now banned.
--
Peter Thoeny - 2015-01-07
This is really strange. After quite a few experiments with different settings I could not reproduce the behaviour.
However, after some hours of staring at the code, I have a hunch what's happening... only that I still have no idea
why it is happening.
Be warned: I have no TWiki 5.1.2 at hand, so this may be thoroughly wrong.
Sten noticed that
setPassword is never called when
$mcp==1, which is a clue. It seems that the detour to redirecting back to the (unchanged) ChangePassword form happens at a very early stage, even before the code in
TWiki::UI::Register::changePassword gets called.
As far as I can say, the only place where
$mcp is evaluated is in
TWiki::UI::checkAccess. This routine checks whether
$mcp is set and the user is on a page which is not ChangePassword. So it would be interesting how control is passed to that piece of code, because
changePassword does not call it. Maybe there is a Plugin with a "very early" handler which does an access check while the
TWiki object is built? "Very early" could mean that web and topic are not yet initialized properly, as you see from your access log, the URL is
/bin/manage/TWiki/WebHome though the form is on ChangePassword.
An easy way to check would be to deactivate all plugins and see whether the error persists.
A more radical method for finding out would be to print a stack trace before the critical line
$session->redirect( $url ); in
TWiki::UI::checkAccess:
if( $session->{users}->getMustChangePassword( $user )
&& "$web.$topic" ne "$TWiki::cfg{SystemWebName}.ChangePassword";
) {
my $wikiname = $session->{users}-&>getWikiName( $user ) || $user;
my $url = $session->getScriptUrl( 1, 'view',
$TWiki::cfg{SystemWebName}, 'ChangePassword',
username => $wikiname,
mcp => '1' );
Carp::cluck("Redirecting due to MCP"); # <--------------here
$session->;redirect( $url );
}
This creates several dozens of lines to Apache's error log for every call, so it should only be activated during the tests.
Good luck!
--
Harald Jörg - 2015-01-12
More or less by accident I stumbled across some more clues (perhaps) friday morning - I just got caught in other stuff so I never got around to post them here..
I found out, that when I am in the "deadlock" of being returned to change password dialog then I can actually break the "deadlock" by removing the cookie set by twiki - after this I can enter credentials and my password can be changed and I can enter twiki normally - voila!
This has been confirmed to work both on IE, Firefox and Chrome.
Could there be something wrong in particular calls to write or read the cookie?
--
Sten Storgaard - 2015-01-12
Thanks again for testing and for the feedback!
The cookie stores information about your client session: On the browser, it is just an ID which is used to construct a filename on the server (provided you're using TWiki's default mechanisms).
With
TemplateLogin, the "session" remains the same even if you log out or log in. So,
bin/manage will read the session variables from the cookie. But I still have no idea how the contents of a session variable (wrong or not) could cause TWiki to perform an action which runs through
TWiki::UI::checkAccess. Unfortunately there have been a couple of changes between TWiki 5 and TWiki 6 with regard to oops and redirects, so my source examination isn't very helpful.
Just another wild guess: Are you using a custom skin which is defined in a TWiki topic? This would open some opportunities where your TWiki reads TWiki topics while mine does not.
The method to get the stack trace would help in any case!
--
Harald Jörg - 2015-01-12
No custom skin - at least not what I am aware of..
There is a company-specific banner in the top of the page, but I guess that's it.
I have added the requested stack traces and the output file is attached - I have filtered output from other IP adresses than my own out
--
Sten Storgaard - 2015-01-13
Perfect! This allowed me to reproduce the problem, though I've yet to nail it down exactly what happens in detail.
- Short answer:
MustChangePassword does not work with ApacheLogin. This is a bug, and still present in TWiki 6.0.
- Somewhat longer answer:
MustChangePassword does not work with Apache authentication and TWiki's default ErrorDocument configuration.
- Longer answer, maybe containing a solution for you: In your access log there are redirections to
login. This usually indicates a TemplateLogin login manager. We missed to ask that question before: If you are intentionally using TemplateLogin, then check your Apache configuration and get rid of the line pr block containing require valid-user. This line makes Apache authentication kick in, regardless of what TWiki thinks you're using for login management.
- Boringly long answer, yet to be investigated fully:
- TWiki has a mechanism to redirect "unauthenticated" requests to the registration page, and per default it tells Apache to send the registration page as a response to unauthenticated requests (
ErrorDocument 401... in Apache's config file). With normal TemplateLogin, Apache should never send a 401 response!
- Your recent error log indeed shows that TWiki calls
checkAccess with web.topic=TWiki.TWikiRegistration, so I assume this mechanism kicked in.
- So, somehow
/bin/manage triggers a 401 status code, I assume by require valid-user in Apache's configuration for that script.
- The 401 status code causes Apache to ask TWiki to
view the registration page... and voila, you are viewing a page but TWiki knows that you need to change your password first.
- Therefore, TWiki throws you back to
ChangePassword.
Basically, The
ChangePassword page is TWiki's reaction on Apaches attempt to display the
ErrorDocument as configured. Manually setting
mcp to 0 breaks the loop because TWiki does no longer redirects
view requests (I wonder: After setting
mcp to 0 and successfully changing the password, did you see the registration page?). Killing the cookie breaks the loop because ... well, I've still to figure that one out. The guesswork is that if there's no session for
bin/manage to work on, it fails to have a user for
getMustChangePassword.
--
Harald Jörg - 2015-01-13
Bingo!
removing "require valid-user" from webserver config indeed solved the problem so our users can now perform a "normal" password reset
Thanks for input!
You mention this is a bug and that it still exist in TWiki 6.0, so I guess I don't need to report it anywhere?
--
Sten Storgaard - 2015-01-14
No, you don't need to report it.... because I did it already:
Bugs:Item7606
--
Harald Jörg - 2015-01-14
I am using
TemplateLogin, but I have no "Require valid-user" directive in my web server configuration. Yet, I have the same issue, I cannot change my password.
In fact, this issue is only with my Firefox browser.
If I use Chrome instead, I have no problem changing my password.
At least, we know a little bit more where the problem comes from...
Anyway, I cannot compell my users to use Chrome, and as for me, my favorite browser is still Firefox...
Meanwhile I will try to deactivate this "mandatory change password" behavior.
--
Etienne Pallier - 2015-09-30
OK, I simply deactivated this "mandatory change password" behavior from my config file (lib/LocalSite.cfg) with this line :
$TWiki::cfg{MustChangePasswordAfterReset} = 0;
Now, when a user resets his password, he can login with the system generated password (sent by email).
Then, he can ALSO change his password with the
ChangePassword page, and it works even with Firefox !
So, for me the problem is solved.
It was just a matter of configuration.
I then suggest that you set this configuration as the default one for all future versions of TWIKI.
--
Etienne Pallier - 2015-09-30
I have the same problem sand solution on version 6.1.0
--
TWiki Guest - 2019-02-28
If you answer a question - or someone answered one of your questions - please remember to edit the page and set the status to answered. The status selector is below the edit box.