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

STARTTLS documentation errors & clarifications #125

Closed
tlhackque opened this issue Jul 8, 2017 · 4 comments
Closed

STARTTLS documentation errors & clarifications #125

tlhackque opened this issue Jul 8, 2017 · 4 comments
Assignees
Milestone

Comments

@tlhackque
Copy link

http://aiosmtpd.readthedocs.io/en/latest/aiosmtpd/docs/smtp.html includes:

tls_context and require_starttls are related to the ESMTP STARTTLS command for secure connections to the server, based on RFC 3207. tls_context is used as the SSL protocol context, and there is no default. tls_context must be given and require_starttls must be True for STARTTLS to be supported.

This is only partially correct, and totally confusing. Better would be:

The STARTTLS option of ESMTP (and LMTP), defined in RFC3207, provides for secure connections to the server. For this option to be available, tls_context must be supplied. tls_context is created with the ssl.create_default_context call from the ssl module, as follows:

ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)

The context must be initialized with a server certificate, private key, and/or intermediate CA certificate
chain with the load_cert_chain method. This can be done with separate files, or an all in one file. Files must be in PEM format. e.g.

ctx.load_cert_chain( config.mta.lmtp_certificate )

A number of exceptions can be generated by these methods, and by SSL connections, which you must be prepared to handle. Complete documentation for the ssl module and ssl context methods is located at https://docs.python.org/3.6/library/ssl.html, and should be reviewed before use; in particular if client authentication and/or advanced error handling is desired.

If require_starttls is true, a TLS session must be initiated for the server to respond to any commands other than EHLO/LHLO, NOOP, QUIT, and STARTTLS.

If require_starttls is false (the default), use of TLS is not required; the client MAY upgrade the connection to TLS, or may use any supported command on an insecure connection.

If tls_context is not supplied, the STARTTLS option will not be advertised, and the STARTTLS command will be rejected. require_starttls is meaningless in this case, and should be false.

@Mortal
Copy link
Contributor

Mortal commented Aug 2, 2017

There was just a StackOverflow question on the topic. It seems currently to be slightly easier to create a TLS-on-connect server than a STARTTLS server. Both could probably be exemplified in the docs.

https://stackoverflow.com/q/45447491/how-do-i-properly-support-starttls-with-aiosmtpd

@tlhackque
Copy link
Author

Examples are a good thing.

But in any case, the description of the parameters & their effects needs to be correct and complete.

These are not mutually exclusive. A first step would be for someone with commit privs to cut and paste the edit that I provided into the docs...

warsaw added a commit that referenced this issue Aug 2, 2017
@warsaw warsaw self-assigned this Aug 2, 2017
@warsaw warsaw added this to the 1.2 milestone Aug 2, 2017
@warsaw
Copy link
Contributor

warsaw commented Aug 2, 2017

Please take a look at #126 - I ended up keeping the discussion of the arguments more terse, and adding a new section that goes into more detail. Now with moar crossreferences!

warsaw added a commit that referenced this issue Aug 3, 2017
* Improve the documentation for the STARTTLS options.

Closes #125

* Add NEWS and bump the version number.
@tlhackque
Copy link
Author

Sorry I'm late. Thanks for addressing this. It's much better. One divot.

I disagree with including the 'and require_starttls should be True" clause in the parameter summary.

I think what I wrote is the correct functional description. A tls_context is required for STARTTLS to be offered. require_starttls disables all but a small subset of commands until a TLS link is established.

"require_starttls should be True" is a value judgement - well intentioned = that security is important. I happen to agree, but it has nothing to do with whether STARTTLS is offered or can be used. In fact, require_starttls can not be used for a public server that accepts mail for local delivery (section 4 of 3207)

A publicly-referenced SMTP server MUST NOT require use of the
STARTTLS extension in order to deliver mail locally.

require_starttls is valuable for a server that requires authentication for the server to accept mail (typically a relay, but sometimes a server that only serves a restricted set of clients). The primary reason is that the most common authentication mechanisms transmit plaintext passwords; these MUST NOT be transmitted unencrypted. A server that functions only as a relay (has no local delivery or is not publicly referenced) can require authentication for all transactions. In this case, require_starttls can reduce the server's attack surface.

Security commentary (3207 and the AUTH/SASL RFCs have a fuller discussion):

TLS serves two functions: verifying that a connection is established to the intended host, and providing confidentiality of the information transferred. In the SMTP/LMTP context, TLS does not provide end-to-end confidentiality of e-mail. It can provide assurance that the email is delivered to the correct host. And in the case of servers that require authentication, it can ensure confidentiality of the authentication process - especially username & password. A plaintext password MUST never be transmitted without TLS or an equivalent security layer.

A server may change the supported commands (listed by HELP and EHLO/HLO) when STARTTLS succeeds. In particular: STARTTLS MUST NOT be offered if a TLS session is active. And plaintext authentication mechanisms SHOULD NOT be offered (and MUST NOT be accepted) UNLESS a TLS session is active. TLS client authentication can also be used as an authentication mechanism - and for authorizing specific mechanism, such as RELAY or ETRN service.

Per RFC 3207, once a TLS session is established, a client MUST discard all knowledge obtained from the SMTP/LMTP server and start again with the ELHO/LHLO sequence.

require_starttls = True is the recommended configuration for servers that offer the STARTTLS service and that require authentication for all transactions. This configuration minimizes the risk that a plaintext password is exposed or that e-mail can be redirected and/or captured by a host that impersonates a server. In this configuration, only the commands necessary for setting up a secure connection are permitted over an insecure connection.

require_starttls = False allows clients that can not establish a TLS connection to submit mail to your server. Generally, your server should only accept local mail without authentication (open relays promote SPAM). The most common authentication methods use plaintext passwords; these MUST NOT be transmitted without an active TLS session.

Although TLS does encrypt e-mail between your server and it's client, it does NOT provide end-to-end encryption of e-mail; in fact, if the client is a relay, e-mail is unlikely to be encrypted while in the relay's queue.

For end-to-end encryption, see S/MIME or PGP.

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

No branches or pull requests

3 participants