| Bug #38939 | MembershipUser.GetPassword(string answer) fails when incorrect answer is passed. | ||
|---|---|---|---|
| Submitted: | 21 Aug 2008 14:19 | Modified: | 5 Sep 2008 16:30 |
| Reporter: | Craig Ritchie | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / NET | Severity: | S2 (Serious) |
| Version: | 5.2.3.0 | OS: | Windows |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | MembershipUser GetPassword | ||
[25 Aug 2008 9: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 13: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 13: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 20: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 20:22]
Reggie Burnett
fixed in 5.3.0
[5 Sep 2008 16: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.

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().