Skip to content

Commit 4dae4b1

Browse files
Tests: regression coverage for the IMAP/POP3 per-connection auth-failure cap (auto-ban disabled, assert connection drops after the cap)
1 parent d4fb80c commit 4dae4b1

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

hmailserver/test/RegressionTests/IMAP/Basics.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,55 @@ public void TestOversizedCommandLiteralRejected()
7171
simulator.Disconnect();
7272
}
7373

74+
[Test]
75+
[Description("Security: with the per-IP auto-ban disabled, a single IMAP connection must still be disconnected after the per-connection authentication-failure cap (defense-in-depth brute-force protection).")]
76+
public void TestPerConnectionLoginFailureCapDisconnects()
77+
{
78+
var settings = SingletonProvider<TestSetup>.Instance.GetApp().Settings;
79+
bool originalAutoBan = settings.AutoBanOnLogonFailure;
80+
settings.AutoBanOnLogonFailure = false;
81+
settings.ClearLogonFailureList();
82+
83+
try
84+
{
85+
SingletonProvider<TestSetup>.Instance.AddAccount(_domain, "capimap@example.test", "secret");
86+
87+
var simulator = new ImapClientSimulator();
88+
simulator.Connect();
89+
90+
string last = "";
91+
bool disconnected = false;
92+
for (int i = 1; i <= 12; i++)
93+
{
94+
try
95+
{
96+
last = simulator.Send("A" + i + " LOGIN capimap@example.test wrongpassword");
97+
}
98+
catch (Exception)
99+
{
100+
disconnected = true;
101+
break;
102+
}
103+
104+
if (last.Contains("Too many invalid logon attempts") || last.Contains("Goodbye"))
105+
{
106+
disconnected = true;
107+
break;
108+
}
109+
}
110+
111+
Assert.IsTrue(disconnected,
112+
"The IMAP connection should have been disconnected after the per-connection authentication-failure cap. Last response: " + last);
113+
114+
simulator.Disconnect();
115+
}
116+
finally
117+
{
118+
settings.AutoBanOnLogonFailure = originalAutoBan;
119+
settings.ClearLogonFailureList();
120+
}
121+
}
122+
74123
[Test]
75124
public void TestAppendDeletedMessage()
76125
{

hmailserver/test/RegressionTests/POP3/Basics.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,59 @@ private string[] GetTestFiles()
3737
return files.ToArray();
3838
}
3939

40+
[Test]
41+
[Description("Security: with the per-IP auto-ban disabled, a single POP3 connection must still be disconnected after the per-connection authentication-failure cap (defense-in-depth brute-force protection).")]
42+
public void TestPerConnectionLoginFailureCapDisconnects()
43+
{
44+
var settings = SingletonProvider<TestSetup>.Instance.GetApp().Settings;
45+
bool originalAutoBan = settings.AutoBanOnLogonFailure;
46+
settings.AutoBanOnLogonFailure = false;
47+
settings.ClearLogonFailureList();
48+
49+
try
50+
{
51+
SingletonProvider<TestSetup>.Instance.AddAccount(_domain, "cappop3@example.test", "secret");
52+
53+
var tc = new TcpConnection();
54+
Assert.IsTrue(tc.Connect(110));
55+
tc.ReadUntil("+OK"); // banner
56+
57+
string last = "";
58+
bool disconnected = false;
59+
for (int i = 1; i <= 12; i++)
60+
{
61+
try
62+
{
63+
tc.Send("USER cappop3@example.test\r\n");
64+
tc.ReadUntil("+OK");
65+
tc.Send("PASS wrongpassword\r\n");
66+
last = tc.Receive();
67+
}
68+
catch (Exception)
69+
{
70+
disconnected = true;
71+
break;
72+
}
73+
74+
if (last.Contains("Too many invalid logon attempts"))
75+
{
76+
disconnected = true;
77+
break;
78+
}
79+
}
80+
81+
Assert.IsTrue(disconnected,
82+
"The POP3 connection should have been disconnected after the per-connection authentication-failure cap. Last response: " + last);
83+
84+
tc.Disconnect();
85+
}
86+
finally
87+
{
88+
settings.AutoBanOnLogonFailure = originalAutoBan;
89+
settings.ClearLogonFailureList();
90+
}
91+
}
92+
4093
[Test]
4194
[Description("Test to send a number of attachments...")]
4295
public void TestAttachmentEncoding()

0 commit comments

Comments
 (0)