Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for AUTH LOGIN and AUTH PLAIN #110

Merged
merged 14 commits into from
Jun 18, 2018

Conversation

jimbobmcgee
Copy link
Contributor

I've had a stab at implementing basic SMTP authentication support. It's not authentication against a specific source, yet (but I've indicated where that might be added), as I don't necessarily believe that real authentication is needed.

The initial use case that I have worked towards is to allow configuring the SMTP server component to require authentication, so as to prove that the SMTP client used by a developer was actually attempting to authenticate. In the past, I've had some junior devs in my team who, when presented with an SMTP server like Papercut (which doesn't currently require any auth), actually forget that they still need to include the ability to configure SMTP authentication in their client apps! By having Papercut able to require authentication (even if that authentication is arbitrary) I might avoid such happenings in the future.

However, it should also provide a reasonable starting point to perform real authentication, if so desired -- the Authenticate method in AuthSmtpCommand.cs could readily be extended to support a real authentication scheme (e.g. a persisted dictionary of username/password, or even an LDAP server), and I've made some implementation notes within the source.

At this stage, I am missing one aspect, which I'm hoping the regular maintainers can assist with -- actually defining and using an application setting to turn on/off the auth requirement on the server. I have added a read/write RequiresAuthentication property to SmtpSession.cs which controls this, figuring that it can be set from an application setting in SmtpProtocol.Begin, but I can't follow how one defines an application setting, reads it and/or persists it through either UI's or Service's settings.

Thoughts/edits are welcome.

Added SmtpSession values to hold settings determining whether authentication is required, and the username that has been authenticated
Supports AUTH LOGIN and AUTH PLAIN, but does nto validate any credentials.  Intended to prove that upstream consumers of SMTP have actually provided credentials, not that they are necessarily correct
Added RequiresAuthentication property to BaseSmtpCommand.  By default this will be `true`, but can be overridded by commands that do not require authentication, such as HELO/EHLO/RSET/QUIT and AUTH itself.

(Figured there were more commands that required authentication than those that didn't, but can semantically alter this if need be)
Also indicated support for AUTH LOGIN and AUTH PLAIN
@Jaben Jaben self-assigned this Jun 15, 2018
@Jaben Jaben added this to the 6.0.0.0 milestone Jun 15, 2018
@AppVeyorBot
Copy link

Build Papercut 5.1.47 failed (commit bf0dbe2916 by @jimbobmcgee)

@Jaben Jaben removed this from the 6.0.0.0 milestone Jun 15, 2018
@Jaben
Copy link
Member

Jaben commented Jun 15, 2018

First of all, thanks for the PR! Finally getting a chance to take a look.

It seems the project has the "AuthSmtpCommand.cs" file excluded. Could you please add?

Copy link
Member

@Jaben Jaben left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor changes :)

// and password -- by sending two consecutive 334 messages. As a foible,
// the two prompts are also base64-encoded. We pre-encode these for some
// tiny micro-optimisation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like, in this situation, "micro-optimization" isn't beneficial -- as it's most likely less clear for other developers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alternatives I can see here are:

  • to send something like $"334 {Convert.ToBase64String(Encoding.Utf8.GetBytes("Username:"))}" each time on the fly
  • for usernamePrompt and passwordPrompt not to be const so the assignment can be made each time, based on the Convert call
  • to uplift usernamePrompt and passwordPrompt to private static readonly class members, so the assignment can be done once, based on the Convert call

Do you have a preference/alternative?

Copy link
Member

@Jaben Jaben Jun 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about a ToBase64() extension? You can make it const/static. But, out of curiosity, I benchmarked the call (using the excellent BenchmarkDotNet) and it's only 75ns (or 0.000075ms) -- not worth optimizing giving it will only be called a few times per connection.

Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I've added a ToBase64String extension to GeneralExtensions (in keeping with AsString) and folded the encoding directly into the SendLine calls.

Added `using Papercut.Network.Protocols;` to gain access to `IConnection.SendLine`
@AppVeyorBot
Copy link

@AppVeyorBot
Copy link

...in favour of calculating Base64 prompts each time
@AppVeyorBot
Copy link

@Jaben Jaben merged commit 3c3a494 into ChangemakerStudios:develop Jun 18, 2018
@jimbobmcgee
Copy link
Contributor Author

Now that this is in, how best to wire up an application setting to the SmtpSession.RequiresAuthentication property, so that a user can enable authentication support?

@Jaben
Copy link
Member

Jaben commented Jun 23, 2018

Inject the ISettingsStore into the SMTP server and get a value "RequiredAuthentication" with a default of false -- then set the value on the session context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants