cosullivan / SmtpServer

A SMTP Server component written in C#
MIT License
692 stars 163 forks source link

Unlimited AUTH attempts #126

Closed large closed 4 years ago

large commented 4 years ago

When a user is trying to authenticate it gets unlimited attempts. Currently testing with Thunderbird. Number of retries does not seems to count while doing authentication while other commands have limits.

Here is a log from an internal testing:

220 SMTP v6.3.0.0 ESMTP ready
EHLO [127.0.0.1]
250-SMTP Hello 127.0.0.1, haven't we met before?
250-PIPELINING
250-8BITMIME
250-SMTPUTF8
250-STARTTLS
250 AUTH PLAIN LOGIN
AUTH PLAIN AGxhcmdlQHdlcm5lci5ubwBncmVnZWdy
535 authentication failed
AUTH LOGIN
334 VXNlcm5hbWU6
bGFyZ2VAd2VybmVyLm5v
334 UGFzc3dvcmQ6
Z3JlZ2Vncg==
535 authentication failed
AUTH PLAIN AGxhcmdlQHdlcm5lci5ubwBncmVnZWdy
535 authentication failed
AUTH LOGIN
334 VXNlcm5hbWU6
bGFyZ2VAd2VybmVyLm5v
334 UGFzc3dvcmQ6
Z3JlZ2Vncg==
535 authentication failed
AUTH PLAIN AGxhcmdlQHdlcm5lci5ubwBncmVnZWdy
535 authentication failed
AUTH LOGIN
334 VXNlcm5hbWU6
bGFyZ2VAd2VybmVyLm5v
334 UGFzc3dvcmQ6
Z3JlZ2Vncg==
535 authentication failed
AUTH PLAIN AGxhcmdlQHdlcm5lci5ubwBncmVnZWdy
535 authentication failed
AUTH LOGIN
334 VXNlcm5hbWU6
bGFyZ2VAd2VybmVyLm5v
334 UGFzc3dvcmQ6
Z3JlZ2Vncg==
535 authentication failed
AUTH PLAIN AGxhcmdlQHdlcm5lci5ubwBncmVnZWdy
535 authentication failed
AUTH LOGIN
334 VXNlcm5hbWU6
bGFyZ2VAd2VybmVyLm5v
334 UGFzc3dvcmQ6
Z3JlZ2Vncg==
535 authentication failed
AUTH PLAIN AGxhcmdlQHdlcm5lci5ubwBncmVnZWdy
535 authentication failed
AUTH LOGIN
334 VXNlcm5hbWU6
bGFyZ2VAd2VybmVyLm5v
334 UGFzc3dvcmQ6
Z3JlZ2Vncg==
535 authentication failed
AUTH PLAIN AGxhcmdlQHdlcm5lci5ubwBncmVnZWdy
535 authentication failed
AUTH LOGIN
334 VXNlcm5hbWU6
bGFyZ2VAd2VybmVyLm5v
334 UGFzc3dvcmQ6
Z3JlZ2Vncg==
535 authentication failed
AUTH PLAIN AGxhcmdlQHdlcm5lci5ubwBncmVnZWdy
535 authentication failed
AUTH LOGIN
334 VXNlcm5hbWU6
bGFyZ2VAd2VybmVyLm5v
334 UGFzc3dvcmQ6
Z3JlZ2Vncg==
535 authentication failed
QUIT
221 bye

There should be a limit and the connection should be dropped if the user fails the authentication for x-number of times. Such implementation would invite to a brute-force ;)

My code returns false on the AuthenticateAsync() if the authentication isn't valid.

Edit: The version show'n in the welcome message is not correct, I am currently using 6.4.0

Edit edit: I created a workaround by adding a counter in the context. Added this in public Task AuthenticateAsync(ISessionContext context, string user, string password, CancellationToken token)

                int AuthRetry = 1;
                if (context.Properties.ContainsKey("AuthRetry"))
                {
                    AuthRetry = (int)context.Properties["AuthRetry"];
                    AuthRetry++;
                    context.Properties.Remove("AuthRetry");
                }
                context.Properties.Add("AuthRetry", AuthRetry);

//Then terminate if number of retries has been reached
                if (AuthRetry == 5)
                {
                    throw new SmtpResponseException(SmtpServer.Protocol.SmtpResponse.ServiceClosingTransmissionChannel);
                }
cosullivan commented 4 years ago

Hi,

Thanks for raising this.

I've just pushed out a new version 6.5.0 which contains a MaxAuthenticationAttempts option to configure the server with. This defaults to 3 so you can change it if you need.

Thanks, Cain.

large commented 4 years ago

Hi @cosullivan worked as a charm :) Nice work!