Bug #38939 MembershipUser.GetPassword(string answer) fails when incorrect answer is passed.
Submitted: 21 Aug 2008 16:19 Modified: 5 Sep 2008 18:30
Reporter: Craig Ritchie
Status: Closed
Category:Connector/Net Severity:S2 (Serious)
Version:5.2.3.0 OS:Microsoft Windows
Assigned to: Target Version:
Tags: MembershipUser GetPassword

[21 Aug 2008 16:19] Craig Ritchie
Description:
Event Type: Information
Event Source: MySQLMembershipProvider
Event Category: None
Event ID: 0
Date: 8/20/2008
Time: 9:02:39 PM
User: N/A
Description:
An exception occurred communicating with the data source.

Action: UpdateFailureCount

Exception: MySql.Data.MySqlClient.MySqlException: There is already an open DataReader
associated with this Connection which must be closed first.
at MySql.Data.MySqlClient.MySqlCommand.CheckState()
at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
at MySql.Web.Security.MySQLMembershipProvider.UpdateFailureCount(Int32 userId, String
failureType, MySqlConnection connection)

How to repeat:
config settings:
  requiresQuestionAndAnswer="true"
  enablePasswordRetrieval="true"
  passwordFormat="Encrypted"

Create a user with a question and answer for password retrieval.
Attempt to call MembershipUser.GetPassword() with wrong answer.

The above exception should be the results.

Suggested fix:
I believe the offending code is the call to UpdateFailureCount within this 'if'
statement:
if (this.RequiresQuestionAndAnswer && !this.CheckPassword(answer, dbpassword,
passwordKey, format))
{
this.UpdateFailureCount(userId, "PasswordAnswer", connection);
throw new MembershipPasswordException(Resources.IncorrectPasswordAnswer);
}

Trying to reuse the connection in this call could be the problem. Everything seems to
work if the correct password answer is passed to GetPassword().
[25 Aug 2008 11:34] Tonci Grgin
Hi Craig and thanks for your report. What puzzles me is what did you expect from c/NET in
case wrong answer is provided?
[25 Aug 2008 15:44] Craig Ritchie
From: http://msdn.microsoft.com/en-us/library/kx96zecz.aspx

"GetPassword calls the MembershipProvider.GetPassword method of the membership provider
referenced by the ProviderName property to retrieve the password for the membership user
from the membership data store. If a password answer is required and an incorrect
password answer is supplied, a MembershipPasswordException is thrown by the membership
provider."

The exception that is thrown is not a MembershipPasswordException but a MySqlException
regarding the reuse of a connection... which seems totally irrelevant to providing a
wrong answer.

Further Information: Disassembled from SqlMembershipProvider:
public override string GetPassword(string username, string passwordAnswer)
{
    if (!this.EnablePasswordRetrieval)
    {
        throw new
NotSupportedException(SR.GetString("Membership_PasswordRetrieval_not_supported"));
    }
    SecUtility.CheckParameter(ref username, true, true, true, 0x100, "username");
    string encodedPasswordAnswer = this.GetEncodedPasswordAnswer(username,
passwordAnswer);
    SecUtility.CheckParameter(ref encodedPasswordAnswer, this.RequiresQuestionAndAnswer,
this.RequiresQuestionAndAnswer, false, 0x80, "passwordAnswer");
    int passwordFormat = 0;
    int status = 0;
    string pass = this.GetPasswordFromDB(username, encodedPasswordAnswer,
this.RequiresQuestionAndAnswer, out passwordFormat, out status);
    if (pass != null)
    {
        return base.UnEncodePassword(pass, passwordFormat);
    }
    string exceptionText = this.GetExceptionText(status);
    if (this.IsStatusDueToBadPassword(status))
    {
        throw new MembershipPasswordException(exceptionText);
    }
    throw new ProviderException(exceptionText);
}

I guess the final answer is that I would expect some exception (preferably a
MembershipPasswordException) indicating that the answer is incorrect as the MSDN document
states.
[25 Aug 2008 15:47] Craig Ritchie
Sorry... looking back over the code I see where the proper exception is going to be
thrown... but...

this line:
  this.UpdateFailureCount(userId, "PasswordAnswer", connection);
is failing so that this line:
  throw new MembershipPasswordException(Resources.IncorrectPasswordAnswer);
is never reached.
[28 Aug 2008 22:21] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/52874
[28 Aug 2008 22:22] Reggie Burnett
fixed in 5.3.0
[5 Sep 2008 18:30] Tony Bedford
An entry has been added to the 5.3.0 changelog:

When called with an incorrect password the MembershipProvider.GetPassword() method threw
a MySQLException instead of a MembershipPasswordException.