Skip to content
This repository has been archived by the owner on Nov 28, 2024. It is now read-only.

Dialer.RequireStartTLS to configure STARTTLS security #25

Closed
wants to merge 7 commits into from
Closed

Dialer.RequireStartTLS to configure STARTTLS security #25

wants to merge 7 commits into from

Conversation

sfllaw
Copy link

@sfllaw sfllaw commented Feb 28, 2018

It is possible to use a man-in-the-middle attack to strip STARTTLS security from an SMTP connection. Because all modern SMTP servers support STARTTLS, we recommend that Dialer.RequireStartTLS be set to mail.MandatoryStartTLS.

For backwards compatibility, this library defaults to mail.OpportunisticStartTLS, which means that the client will fallback to a cleartext connection if the SMTP server does not support the STARTTLS extension.

This has no effect on SMTPS connections where TLS wraps the connection itself.

Closes #23.

In order to prevent `mail.doTestSendMail` from being overwhelmed by
parameters, stop creating `mockClient` inside that method and have its
caller create it.

Since there are `testSendMail` and `testSendMailTimeout` helpers, they
create the `mockClient`.
When `mockClient.startTLS` is true, then an SMTP transaction asking
for the STARTTLS extension will find it available. Otherwise, it is
missing.
It is possible to use a man-in-the-middle attack to strip STARTTLS
security from an SMTP connection. Because all modern SMTP servers
support STARTTLS, we recommend that `Dialer.RequireStartTLS` be set to
`mail.MandatoryStartTLS`.

For backwards compatibility, this library defaults to
`mail.OpportunisticStartTLS`, which means that the client will
fallback to a cleartext connection if the SMTP server does not support
the STARTTLS extension.

This has no effect on SMTPS connections where TLS wraps the connection
itself.
@sfllaw
Copy link
Author

sfllaw commented Feb 28, 2018

@ivy Please review this draft patch. I'd be happy to take any suggestions on how to make things simpler when it comes to setting options on the Dialer.

@@ -27,9 +27,17 @@ type Dialer struct {
// most cases since the authentication mechanism should use the STARTTLS
// extension instead.
SSL bool
// TSLConfig represents the TLS configuration used for the TLS (when the
// TLSConfig represents the TLS configuration used for the TLS (when the
Copy link

Choose a reason for hiding this comment

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

Good catch!

Copy link

@ivy ivy left a comment

Choose a reason for hiding this comment

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

I only have a couple nitpicks. Everything else looks good to me!

smtp.go Outdated
// but we recommend MandatoryStartTLS for all modern SMTP servers.
//
// This option has no effect if SSL is set to true.
RequireStartTLS StartTLSSecurity
Copy link

Choose a reason for hiding this comment

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

I think StartTLSPolicy would be a more fitting name for both RequireStartTLS and StartTLSSecurity.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed in 0c066ca.

smtp.go Outdated
if !d.SSL && d.RequireStartTLS != NoStartTLS {
ok, _ := c.Extension("STARTTLS")
if !ok && d.RequireStartTLS == MandatoryStartTLS {
err := fmt.Errorf(
Copy link

Choose a reason for hiding this comment

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

We should export an error for this (e.g. ErrStartTLSUnsupported).

Copy link
Author

Choose a reason for hiding this comment

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

Fixed in d3eed43, but named StartTLSUnsupportedError to follow Go conventions: https://blog.golang.org/error-handling-and-go

Copy link

Choose a reason for hiding this comment

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

That much better than my suggestion. I like your use of StartTLSPolicy.String() for handling the error message.😄

Instead of returning a bare error, `Dial` returns
`StartTLSUnsupportedError` when `Dialer.StartTLSPolicy` requires
STARTTLS, but it is unsupported by the server.
@ivy ivy closed this in 7510912 Mar 1, 2018
ivy added a commit that referenced this pull request Mar 1, 2018
Add Dialer.StartTLSPolicy for securing STARTTLS
@ivy
Copy link

ivy commented Mar 1, 2018

@sfllaw Thanks for implementing this along with the changes I suggested. 👍

@sfllaw
Copy link
Author

sfllaw commented Mar 1, 2018

@ivy Thanks for catching the missing change in CHANGELOG.md.

Do you have plans to release 2.2.0 soon? I'd like to tighten up STARTTLS in some of our code. 😄

@ivy
Copy link

ivy commented Mar 1, 2018

@sfllaw Sure thing, I tagged and released 2.2.0. Thanks again for helping tighten up security! 👍

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

Successfully merging this pull request may close these issues.

2 participants