Several comments narrated the reasoning that produced the code rather than what a reader needs. Two also outlived their subject: ConsumeAuthId's summary and its call site both still claimed the id is spent whether or not it vouches, which stopped being true when ownership checks moved ahead of the removal.
74 lines
3 KiB
C#
74 lines
3 KiB
C#
using System;
|
|
using Server.Accounting;
|
|
using Server.Accounting.Security;
|
|
using Xunit;
|
|
|
|
namespace Server.Tests.Accounting;
|
|
|
|
[Collection("Sequential UOContent Tests")]
|
|
public class AccountPasswordTests : IDisposable
|
|
{
|
|
private const string Password = "hunter2";
|
|
|
|
// CurrentAlgorithm is process-wide state shared with the rest of the collection.
|
|
private readonly PasswordProtectionAlgorithm _originalAlgorithm = AccountSecurity.CurrentAlgorithm;
|
|
|
|
public void Dispose() => AccountSecurity.CurrentAlgorithm = _originalAlgorithm;
|
|
|
|
[Theory]
|
|
[InlineData(PasswordProtectionAlgorithm.SHA1)]
|
|
[InlineData(PasswordProtectionAlgorithm.SHA2)]
|
|
[InlineData(PasswordProtectionAlgorithm.PBKDF2)]
|
|
[InlineData(PasswordProtectionAlgorithm.Argon2)]
|
|
public void NewAccount_CanLogIn(PasswordProtectionAlgorithm algorithm)
|
|
{
|
|
AccountSecurity.CurrentAlgorithm = algorithm;
|
|
var account = new Account($"new-{algorithm}-user", Password);
|
|
|
|
Assert.Equal(algorithm, account.PasswordAlgorithm);
|
|
Assert.True(account.CheckPassword(Password));
|
|
Assert.False(account.CheckPassword("wrong-password"));
|
|
}
|
|
|
|
// SetPassword assigns PasswordAlgorithm before deriving the phrase from it. Reversed, the hash
|
|
// is salted by the outgoing algorithm's rule but stored under the incoming one, which verifies
|
|
// once and then never again.
|
|
[Theory]
|
|
[InlineData(PasswordProtectionAlgorithm.SHA1)]
|
|
[InlineData(PasswordProtectionAlgorithm.SHA2)]
|
|
[InlineData(PasswordProtectionAlgorithm.PBKDF2)]
|
|
public void UpgradingAlgorithm_DoesNotLockTheAccountOut(PasswordProtectionAlgorithm from)
|
|
{
|
|
AccountSecurity.CurrentAlgorithm = from;
|
|
var account = new Account($"upgrade-{from}-user", Password);
|
|
Assert.True(account.CheckPassword(Password));
|
|
|
|
AccountSecurity.CurrentAlgorithm = PasswordProtectionAlgorithm.Argon2;
|
|
|
|
Assert.True(account.CheckPassword(Password));
|
|
Assert.Equal(PasswordProtectionAlgorithm.Argon2, account.PasswordAlgorithm);
|
|
|
|
// Must verify against what the rehash wrote.
|
|
Assert.True(account.CheckPassword(Password));
|
|
Assert.False(account.CheckPassword("wrong-password"));
|
|
}
|
|
|
|
[Fact]
|
|
public void StaleArgon2Parameters_AreRehashedOnLogin()
|
|
{
|
|
AccountSecurity.CurrentAlgorithm = PasswordProtectionAlgorithm.Argon2;
|
|
var account = new Account("stale-params-user", Password);
|
|
|
|
// The shipping default before this change: Argon2i, m=8192, t=3, p=1.
|
|
account.Password =
|
|
"$argon2i$v=19$m=8192,t=3,p=1$LD1XJz7P3wQmIJ+Tu6ScgA$NO5hBABsHQ172C5nDO2X4gWnB4jDef3x6WhLdVE2LFw";
|
|
|
|
Assert.True(account.CheckPassword(Password));
|
|
Assert.StartsWith("$argon2id$v=19$m=16384,t=1,p=1$", account.Password);
|
|
|
|
// Already current: verifying again must not rewrite the hash.
|
|
var afterFirst = account.Password;
|
|
Assert.True(account.CheckPassword(Password));
|
|
Assert.Equal(afterFirst, account.Password);
|
|
}
|
|
}
|